That isn't the problem. The trouble is (!a)|| b is not the same as !(a || b). You effectively wrote the former because ! has higher precedence than ||, so it will apply to a single term unless you put the expression inside parens.
Adding Oangband magic realms/spellbooks. What changes do I need to make?
Collapse
X
-
Thanks! That helped. Now it works.
/* Exclude monsters that are invisible or out of range */
if (!(rf_has(mon->race->flags, RF_INVISIBLE ||
mon->m_timed[MON_TMD_INVISIBLE]) ||
mflag_has(mon->mflag, MFLAG_UNAWARE)))
{
Does this look right?Comment
-
Comment
-
Would an edited version of this do the trick?
/**
* Monster self-healing.
*/
bool effect_handler_MON_HEAL_HP(effect_handler_context_ t *context)
{
int midx = cave->mon_current;
int amount = effect_calculate_value(context, FALSE);
struct monster *mon = midx > 0 ? cave_monster(cave, midx) : NULL;
char m_name[80], m_poss[80];
bool seen;
if (!mon) return TRUE;
/* Get the monster name (or "it") */
monster_desc(m_name, sizeof(m_name), mon, MDESC_STANDARD);
/* Get the monster possessive ("his"/"her"/"its") */
monster_desc(m_poss, sizeof(m_poss), mon, MDESC_PRO_VIS | MDESC_POSS);
seen = (!player->timed[TMD_BLIND] && mflag_has(mon->mflag, MFLAG_VISIBLE));
/* Heal some */
mon->hp += amount;
/* Fully healed */
if (mon->hp >= mon->maxhp) {
mon->hp = mon->maxhp;
if (seen)
msg("%s looks REALLY healthy!", m_name);
else
msg("%s sounds REALLY healthy!", m_name);
} else if (seen) { /* Partially healed */
msg("%s looks healthier.", m_name);
} else {
msg("%s sounds healthier.", m_name);
}
/* Redraw (later) if needed */
if (player->upkeep->health_who == mon)
player->upkeep->redraw |= (PR_HEALTH);
/* Cancel fear */
if (mon->m_timed[MON_TMD_FEAR]) {
mon_clear_timed(mon, MON_TMD_FEAR, MON_TMD_FLG_NOMESSAGE, FALSE);
msg("%s recovers %s courage.", m_name, m_poss);
}
return TRUE;
}Comment
-
bool effect_handler_MON_TIMED_INC:INVISIBLE(effect_hand ler_context_t *context)
{
int midx = cave->mon_current;
int amount = effect_calculate_value(context, FALSE);
struct monster *mon = midx > 0 ? cave_monster(cave, midx) : NULL;
char m_name[80], m_poss[80];
bool seen;
if (!mon) return TRUE;
/* Get the monster name (or "it") */
monster_desc(m_name, sizeof(m_name), mon, MDESC_STANDARD);
/* Get the monster possessive ("his"/"her"/"its") */
monster_desc(m_poss, sizeof(m_poss), mon, MDESC_PRO_VIS | MDESC_POSS);
seen = (!player->timed[TMD_BLIND] && mflag_has(mon->mflag, MFLAG_VISIBLE));
I get stuck here though...
something like: if monster has MON_TIMED_INC:INVISIBLE lose (mon->mflag, MFLAG_VISIBLE) and then redraw something?Comment
-
Not quite. There is a special function for doing that kind of thing, called update_mon in mon-utils.c. You need to update the function to do the right thing with the invisibility flag, and call it when the monster uses the spell. You also need to call it when the timer goes to zero. So the spell should be essentially :
Set the flag to the new timed value
call the function
return.
It should not mess with seen at all. Just say "{The monster} calls a cloak of darkness about it/him/her" and call the function.
It's important to fix it here, because this update_mon gets called every time the monster moves, and it is where the monster is determined to be visible or not.
Edit: The function update_mon is called a "Listener" in computer science, that it is listens to "events" that affect some object. If angband were a newer product, this kind of thing would happen automatically every time the monster changed (via "accessor functions" on the monster.) The update_mon would never be called directly. Instead there would be a tiny function that updates the m_timed values and calls any listener(s). (There already is such a function for the player timed values.)
https://en.wikipedia.org/wiki/Event_(computing)
Last edited by Pete Mack; July 16, 2016, 05:38.Comment
-
It looks like I already updated this part some:
/* Learn about invisibility */
rf_on(lore->flags, RF_INVISIBLE);
/* Handle "invisible" monsters */
if (rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ) {
/* See invisible */
if (player_of_has(player, OF_SEE_INVIS))
{
/* Easy to see */
easy = flag = TRUE;
}
Edit: Do I put the spell beneath the "Learn about invisibility" section?Comment
-
Ok, I don't really know how to do that, but I wrote this (I don't know if I am on the right track):
"if (mon_has(mon->m_timed[MON_TMD_INVISIBLE])
"
Do I need to tell it to give the monster mon->m_timed[MON_TMD_INVISIBLE] or does this (from monster-spell.txt):
"name:INVISIBLE
hit:100
effect:MON_TIMED_INC:INVISIBLE
dice:50
power:40
lore:make self invisible
message-vis:{name} calls a cloak of darkness about {pronoun} body."
do that?
(I put the message you gave into the text file)
Edit: I am trying to figure out as much as possible on my own. But all I've ever done with programming before was make a program that made a window and then drew random shapes all over it one at a time, and that was years ago.Comment
-
Oh, and Nick (I saw you were on the thread), the spell realms work now except for displaying the book names in inventory (and store inventory) lists. I can't say the same for the individual spells yet.
(Right now I am working on something else though.)Comment
-
OK, so when you write effect:MON_TIMED_INC:INVISIBLE in the edit file, that means that the effect MON_TIMED_INC gets called with the parameter MON_TMD_INVISIBLE in context->p1. You don't have to write a function called effect_handler_MON_TIMED_INC:INVISIBLE to handle it.
The handler for MON_TIMED_INC is pretty simple, it just calls the code in mon-timed.c.
If you look in mon-timed.c, you can see that this the code handles printing the messages when monsters become/stop being invisible. It all happens in mon_set_timed(); see the variable m_note and the call to add_monster_message(). Those extra lines you added to list-mon-timed.h and list-mon-message.h make this all work. This will be in addition to the message you've set in the monster spell file.
What Pete said about calling update_mon() still stands, but you'd want to add a call in mon_set_timed() so when the invisiblily timed effect changes you call it.
In this bit:
Code:if (resisted) m_note = MON_MSG_UNAFFECTED; else mon->m_timed[ef_idx] = timer; if (player->upkeep->health_who == mon) player->upkeep->redraw |= (PR_HEALTH); /* Update the visuals, as appropriate. */ player->upkeep->redraw |= (PR_MONLIST);
Code:if (ef_idx == MON_TMD_INVISIBLE) { update_mon(mon, cave, false); }
Code:if (ef_idx == MON_TMD_INVISIBLE) return (false);
It looks like I already updated this part some:
Code:/* Learn about invisibility */ rf_on(lore->flags, RF_INVISIBLE); /* Handle "invisible" monsters */ if (rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ) { /* See invisible */ if (player_of_has(player, OF_SEE_INVIS)) { /* Easy to see */ easy = flag = TRUE; }
Code:if (rf_has(mon->race->flags, RF_INVISIBLE) || mon->m_timed[MON_TMD_INVISIBLE])
takkaria whispers something about options. -more-Comment
-
Comment
-
takkaria whispers something about options. -more-Comment
-
Ok, I did this:
/* Determine if the monster resisted or not, if appropriate */
if (check_resist)
resisted = mon_resist_effect(mon, ef_idx, timer, flag);
if (ef_idx == MON_TMD_INVISIBLE) return (false);
if (resisted)
m_note = MON_MSG_UNAFFECTED;
else
mon->m_timed[ef_idx] = timer;
if (player->upkeep->health_who == mon)
player->upkeep->redraw |= (PR_HEALTH);
if (ef_idx == MON_TMD_INVISIBLE) {
update_mon(mon, cave, false);
}
And changed the parentheses.
I really don't know how to do this though:
Set the flag to the new timed value
call the function
return.Comment
Comment