Welcome to the Builder Academy

Question Mob Switching

More
09 Mar 2026 01:48 #10992 by soth
Mob Switching was created by soth
Hello,
Not sure if this has been implemented yet by someone or not, search didn't really find anything when I tried it. I had thought about the T/H/D (tank, healer, dps) and then thought about how I could make mobs switch targets to start with based on an aggro table or for instance if the DPS was doing crazy amount of damage compared to the tank. Possibly implementing a threat table of some sort and having it check each round or that might be too intensive? What are some thoughts on this and any ideas on how to implement it?

If this was implemented I could see giving the tank a taunt, provoke or other skill to try and hold aggro.

TY!

Please Log in or Create an account to join the conversation.

More
10 Mar 2026 13:52 #10993 by WhiskyTest
Replied by WhiskyTest on topic Mob Switching
Sounds like a neat feature! 

I would take a look at the existing aggressive mob code block on line 92 in mobact.c

You can plagiarize most of it to create a function that looks for the player with the highest 'threat' in the room.
So instead of all those checks for mob flags, just look at the value of GET_THREAT(vict) and remember who has the highest.
Call it when you want to evaluate target switching. Eg: from mobile_activity it's every 10 seconds, or perhaps you want it every combat round.


I imagine 'threat' would be a number that goes higher when you do amazing things, and wears off after some time. Adding another 'points' stat could work, eg:

struct char_point_data
{
+  sh_int threat;     /**< Current Threat level  */

   sh_int mana;     /**< Current mana level  */
etc..


Make a macro
+ #define GET_THREAT(ch)    ((ch->points.threat))

Have threat clear at the end of the fight, or each tick, or mud events etc.
The following user(s) said Thank You: thomas

Please Log in or Create an account to join the conversation.

More
11 Mar 2026 11:49 - 11 Mar 2026 11:57 #10996 by WhiskyTest
Replied by WhiskyTest on topic Mob Switching
I changed my mind. Having threat attached to the player would mean all mobs would treat them the same way, but that's not necessarily an accurate reflection..
What if said player hadn't even attacked a mob - why would that particular mob consider them a threat?

Perhaps having each mob use their own threat assessment works better. We do a similar thing with mob memory..

If we created a new struct that holds a player pointer and their threat level per mob:
(Warning - Semi-tested code follows! :) )
Code:
/** Special data used by NPCs, not PCs */ struct mob_special_data {   memory_rec *memory; /**< List of PCs to remember */   byte attack_type;   /**< The primary attack type (bite, sting, hit, etc.) */   byte default_pos;   /**< Default position (standing, sleeping, etc.) */   byte damnodice;     /**< The number of dice to roll for damage */   byte damsizedice;   /**< The size of each die rolled for damage. */   struct threat_data *threat_list; }; struct threat_data {   struct char_data *ch;   int threat;   struct threat_data *next; };

When we damage a mob we add threat:
Code:
void add_threat(struct char_data *mob, struct char_data *ch, int amount) {   struct threat_data *t;   if (!IS_NPC(mob) || !ch)     return;   for (t = mob->mob_specials.threat_list; t; t = t->next) {     if (t->ch == ch) {       t->threat += amount;       return;     }   }   CREATE(t, struct threat_data, 1);   t->ch = ch;   t->threat = amount;   t->next = mob->mob_specials.threat_list;   mob->mob_specials.threat_list = t; }

And then during combat you can evaluate which character in the threat_list has the highest value:
Code:
struct char_data *get_top_threat(struct char_data *mob) {   struct threat_data *t;   struct char_data *target = NULL;   int highest = 0;   for (t = mob->mob_specials.threat_list; t; t = t->next) {     if (t->ch && t->threat > highest && IN_ROOM(t->ch) == IN_ROOM(mob)) {       highest = t->threat;       target = t->ch;     }   }   return target; }

Then in the fight sequence target the highest threat player, somewhere in perform_violence?
Code:
      target = get_top_threat(ch);       if (target && FIGHTING(ch) != target) {         send_to_room(IN_ROOM(ch), "%s switches target to %s.\r\n", GET_NAME(ch), GET_NAME(target));         set_fighting(ch, target);       }

Ps: you'd need to clear memory to prevent leaks when the mob dies, or combat stops. 

This approach is a bit more involved for sure, but I feel it gives more flexibility to expand.
You can add functions that reduce specific threat , like a skill that reduces threat by 20%, taunt could double your threat, stitch up a friend by increasing their threat instead of your own...
Last edit: 11 Mar 2026 11:57 by WhiskyTest.

Please Log in or Create an account to join the conversation.

Time to create page: 0.236 seconds