View Single Post
Old June 25, 2020, 05:15   #1
Celiend
Rookie
 
Join Date: Jun 2020
Posts: 8
Celiend is on a distinguished road
Monster_Base Flags

Hey there!

I have been messing around with some of the code on the "4.2-Release" branch of Angband Vanilla. Unfortunately, I'm finding that this codebase is *SO* large that I'm having trouble figuring out how to grab simple parameters for alteration.

So... what I'm trying to do is to figure out how to alter the function "effect_handler_TAP_UNLIFE" in the file "effects.c".

Origin_Behavior: Current behavior in "4.2-Release" is described as: "When 'Tap Unlife' is cast by the necromancer; it selects the closest undead monster in Line of Sight, and it damages the undead monster as it restores some spell points to the necromancer based on the damage to the undead monster."

Current behavior:
Code:
bool effect_handler_TAP_UNLIFE(effect_handler_context_t *context)
{
	int amount = effect_calculate_value(context, false);
	struct loc target;
	struct monster *mon = NULL;
	char m_name[80];
	int drain = 0;
	bool fear = false;
	bool dead = false;

	context->ident = true;

	/* Closest living monster */
	if (!target_set_closest(TARGET_KILL, monster_is_undead)) {
		return false;
	}
	target_get(&target);
	mon = target_get_monster();

	/* Hurt the monster */
	monster_desc(m_name, sizeof(m_name), mon, MDESC_TARG);
	msg("You draw power from the %s.", m_name);
	drain = MIN(mon->hp, amount) / 4;
	dead = mon_take_hit(mon, amount, &fear, " is destroyed!");

	/* Gain mana */
	effect_simple(EF_RESTORE_MANA, context->origin, format("%d", drain), 0, 0,
				  0, 0, 0, NULL);

	/* Handle fear for surviving monsters */
	if (!dead && monster_is_visible(mon)) {
		message_pain(mon, amount);
		if (fear) {
			add_monster_message(mon, MON_MSG_FLEE_IN_TERROR, true);
		}
	}

	return true;
}

Changed_Behavior: Intended change to the behavior to the "Tap Unlife" spell in a private branch called "Necromancer_Changes" is: "When 'Tap Unlife' is cast by the necromancer; it selects all undead monsters in Line of Sight and it damages the undead monsters as it restores some spell points to the necromancer based on the damage inflicted to one instance of an undead monster."

My code changes:

Code:
bool effect_handler_TAP_UNLIFE(effect_handler_context_t *context)
{
	int amount = effect_calculate_value(context, false);
	struct loc target;
	struct monster *mon = NULL;
	char m_name[80];
	int drain = 0;
	bool fear = false;
	bool dead = false;
        
        msg("XXXCalled Tap Unlife:  amount: %i.",amount);

	context->ident = true;

	/* Closest living monster */
	if (!target_set_closest(TARGET_KILL, monster_is_undead)) {
		return false;
	}
	target_get(&target);
	mon = target_get_monster();
        
        struct loc origin = origin_get_loc(context->origin);
        
        int i = 0;
        
        for (i = 1; i < cave_monster_max(cave); i++) {
            struct monster *mon = cave_monster(cave, i);

        	/* Paranoia -- Skip dead monsters */
            if (!mon->race) continue;

	    /* Require line of sight */
            if (!los(cave, origin, mon->grid)) continue;

	    /* Jump directly to the monster */
            	/* Hurt the monster */
            if(monster_is_undead)
            {
                monster_desc(m_name, sizeof(m_name), mon, MDESC_TARG);
                msg("You draw power from the %s.", m_name);
                drain = MIN(mon->hp, amount) / 4;
                dead = mon_take_hit(mon, amount, &fear, " is destroyed!");        
            }
	    
            context->ident = true;
	}

	/* Hurt the monster */
        /*
        monster_desc(m_name, sizeof(m_name), mon, MDESC_TARG);
	msg("You draw power from the %s.", m_name);
	drain = MIN(mon->hp, amount) / 4;
	dead = mon_take_hit(mon, amount, &fear, " is destroyed!"); 
         */
	
	/* Gain mana */
	effect_simple(EF_RESTORE_MANA, context->origin, format("%d", drain), 0, 0,
				  0, 0, 0, NULL);

	/* Handle fear for surviving monsters */
        /*
        if (!dead && monster_is_visible(mon)) {
		message_pain(mon, amount);
		if (fear) {
			add_monster_message(mon, MON_MSG_FLEE_IN_TERROR, true);
		}
	} 
         */
	

	return true;
}

You'll notice if you test this code that every monster in Line of Sight is currently targeted for damage (Undead or not) [Apparently, 'monster_is_undead' currently always evaluates to 'true'] as long as at least one Undead is in Line of Sight.

This behavior is undesirable... I would like to target undead exclusively with the casting of "Tap Unlife". I've been trying to figure out how to grab a property for a given monster that will tell me if the monster has a flag, 'UNDEAD'... but I'm coming up dry.

For those of you with more experience editing the vanilla Angband codebase... if you know how to resolve this problem... would you mind suggesting a solution?

Note... I have NO INTENTION of replacing the current vanilla behavior with my changes as part of "canon"; I'm just... trying stuff right now.

Last edited by Celiend; June 25, 2020 at 05:28.
Celiend is offline   Reply With Quote