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...