20 May, 2009, boblinski wrote in the 1st comment:
Votes: 0
Hi there, I'm trying to create a command that will make a tick happen instantly…

This is what I've got in act_wiz.c:
void do_forcetick (CHAR_DATA *ch, char * argument)
{
update_handler();
send_to_char ("FORCETICK!\r\n", ch);

return;
}


It doesn't do what I'm wanting it to do though, for example.. I want to be able to spam out "forcetick" a dozen times and reduce the affect timers so I can test things easier… but it doesn't work, see:
Quote
<32076hp 30227m 30727mv> aff

You are affected by the following spells:
Spell: bearcall : modifies none by 0 for 29 hours

<32076hp 30227m 30727mv> forcetick

FORCETICK!

<32076hp 30227m 30727mv> aff

You are affected by the following spells:
Spell: bearcall : modifies none by 0 for 29 hours


Any improvements/ideas?
20 May, 2009, Sharmair wrote in the 2nd comment:
Votes: 0
The update_handler() is called on each pulse, and in stock ROM that is 4 times a second. So,
unless the next pending pulse would happen to call the thing you are looking for (in your case,
the char_update function) you will not notice anything. Being that char_update() is only called
once every 240 pulses, it is rather unlikely you will catch it at the right time (you do advance
game time by 1/4 of a second though, so the next char_update() will come a bit earlier).

You could do a couple things. One is just to call char_update() instead of update_handler(),
this would just add extra char_updates, but not advance other timing events (the time event
known as the tick actually calls weather_update(), char_update() and obj_update() and there
are a number of other time events unrelated to the tick). You could also truly advance time
by calling update_handler() in a loop using 4 loops per second you want to advance (240 per
minute/tick). You could either have it run so much time, or add an argument for the time to
advance.
20 May, 2009, quixadhal wrote in the 3rd comment:
Votes: 0
If you want to force a tick to happen as soon as feasable, the simplest way is to forcibly adjust the tick counter variable so it will go off on the next call to update_handler(). I'm not that familiar with ROM, but in my ancient Diku, there are several pulse variables which serve the same function. In my case, each time through the update loop, I decrement each pulse variable and when it hits 0, I do whatever needs to be done for that class of thing, and then reset it to my define'd constant + a small random number. In ROM, there is probably only a single counter that increments and does the actions when it's equal to variable % PULSE_FOO or whatever. In that case, you'd increment the variable so it's equal to the next modulo of PULSE_FOO.

Be aware that this will screw up timing, so if you have spells that are supposed to last for X seconds (counting off ticks), they will expire sooner than expected.
20 May, 2009, David Haley wrote in the 4th comment:
Votes: 0
Quote
Be aware that this will screw up timing, so if you have spells that are supposed to last for X seconds (counting off ticks), they will expire sooner than expected.

I think that's exactly the intention, actually. :tongue:
20 May, 2009, boblinski wrote in the 5th comment:
Votes: 0
Yeah it is, but I'm not quite sure what you're exactly telling me to do..

Could I just edit do_forcetick to be:

void do_forcetick (CHAR_DATA *ch, char * argument)
{
weather_update ();
char_update ();
obj_update ();
aggr_update ();
tail_chain ();

update_handler();
send_to_char ("FORCETICK!\r\n", ch);

return;
}
20 May, 2009, David Haley wrote in the 6th comment:
Votes: 0
No, he's saying that there are several variables that basically count the number of pulses until something happens. (A pulse is the thing that happens several times a second.) When the counter hits zero, the thing (whatever it is: weather, combat rounds, etc.) is taken care of, and the counter is reset.

So, if you were to just set that counter to zero, and do nothing else, on the next pulse a tick would happen.

I don't know what happens if you set just the tick counter to zero and don't take care of the other things, though. I'm not sure if there are dependencies between the various update routines.
20 May, 2009, boblinski wrote in the 7th comment:
Votes: 0
David Haley said:
So, if you were to just set that counter to zero, and do nothing else, on the next pulse a tick would happen.


Okay, so how do I go about doing this?

So far I have failed to do so.
20 May, 2009, David Haley wrote in the 8th comment:
Votes: 0
You need to figure out what the counter variable is (see the update functions you've already found) and then just set it to zero.
20 May, 2009, Sandi wrote in the 9th comment:
Votes: 0
I'm not thinking too clearly right now, but I suspect you want something like this:

void force_tick( CHAR_DATA *ch, int time )
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;

for ( paf = ch->affected; paf != NULL; paf = paf_next )
{
paf_next = paf->next;
if (af->type == gsn_bearcall)
{
paf->duration = time;
}
}
return;
}


To make it more generally useful, I suppose you'd want to add an argument (that you test) for changing the gsn.
20 May, 2009, Zeno wrote in the 10th comment:
Votes: 0
Er no, it has nothing to do with affects. There's something like a single global variable.
20 May, 2009, David Haley wrote in the 11th comment:
Votes: 0
Well, she's right that if the idea is just to make effects die more quickly, you can just edit the effect. It occurs to me that if the intention really is just to make effects go away, there are far easier ways of doing that, namely just removing the effects…
20 May, 2009, Davion wrote in the 12th comment:
Votes: 0
They're static ints in update_handler.

void update_handler( void )
{
static int pulse_area;
static int pulse_mobile;
static int pulse_violence;
static int pulse_point;
static int pulse_music;


You have to make a way, so you can set those int's to 0 whenever you want.
20 May, 2009, David Haley wrote in the 13th comment:
Votes: 0
What! There is encapsulation and data hiding in the codebase?? Shocking! :smirk:
20 May, 2009, Kline wrote in the 14th comment:
Votes: 0
boblinski said:
Yeah it is, but I'm not quite sure what you're exactly telling me to do..

Could I just edit do_forcetick to be:

void do_forcetick (CHAR_DATA *ch, char * argument)
{
weather_update ();
char_update ();
obj_update ();
send_to_char ("FORCETICK!\r\n", ch);

return;
}


The above would be fine, and in fact is almost identical to how what you're after is implemented in most stock GodWars (AFAIK, it was in the copy I have, anyhow).
21 May, 2009, boblinski wrote in the 15th comment:
Votes: 0
This is the code:
void do_forcetick (CHAR_DATA *ch, char * argument)
{
weather_update(); /*line 4972*/
char_update();
obj_update();
send_to_char ("FORCETICK!\n\r", ch);

return;
}


This is the warning:
Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/act_wiz.o act_wiz.c
act_wiz.c: In function `do_forcetick':
act_wiz.c:4972: warning: implicit declaration of function `weather_update'
act_wiz.c:4973: warning: implicit declaration of function `char_update'
act_wiz.c:4974: warning: implicit declaration of function `obj_update'
rm -f rom
21 May, 2009, boblinski wrote in the 16th comment:
Votes: 0
Hmmm I added this at the top of act_wiz.c:

void weather_update args ((void));
void char_update args ((void));
void obj_update args ((void));


It seems to stop the warnings, but is it the correct fix?
21 May, 2009, David Haley wrote in the 17th comment:
Votes: 0
Yes, it was complaining about the functions not being declared, so declaring them (by adding their prototype) is the right thing to do…
21 May, 2009, Sandi wrote in the 18th comment:
Votes: 0
Zeno said:
Er no, it has nothing to do with affects. There's something like a single global variable.

*sigh* In his first post, he showed the output of 'affects', and complained that merely running update_hander wasn't working. Shamair then explained why. A little further down, David pointed out that what he really wanted to do was reduce the counter variable of the affect being tested. So….

void do_now( CHAR_DATA *ch, char *argument )
{
char arg1[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
int sn;
bool done = FALSE;

argument = one_argument( argument, arg1 );

if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
{
send_to_char( "That player is not here.\r\n", ch);
return;
}

sn = skill_lookup(argument);

if ( sn < 0 )
{
send_to_char( "Sorry, no such spell.\r\n", ch );
return;
}

for ( paf = victim->affected; paf != NULL; paf = paf_next )
{
paf_next = paf->next;
if ( paf->type == sn )
{
paf->duration = 0;
done = TRUE;
}
}

if ( !done )
act( "$N is not affected by $t.",ch, argument, victim, TO_CHAR );
else
send_to_char( "Spell duration reduced.\r\n", ch );

return;
}


There you go, bob. Fully tested, help file below. No credit required.

Syntax: now <char name> <spell name>

This command will reduce a spell's duration to 0 so the spell will expire on the next tick. Useful for testing commands that have effects when they wear off, and you don't want to wait to see what happens.
21 May, 2009, Hades_Kane wrote in the 19th comment:
Votes: 0
boblinski said:
This is the code:
void do_forcetick (CHAR_DATA *ch, char * argument)
{
weather_update(); /*line 4972*/
char_update();
obj_update();
send_to_char ("FORCETICK!\n\r", ch);

return;
}


This is the warning:
Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/act_wiz.o act_wiz.c
act_wiz.c: In function `do_forcetick':
act_wiz.c:4972: warning: implicit declaration of function `weather_update'
act_wiz.c:4973: warning: implicit declaration of function `char_update'
act_wiz.c:4974: warning: implicit declaration of function `obj_update'
rm -f rom



The "implicit declaration of function" warnings come from when you are using a function that might declared elsewhere in the code, but that file specifically doesn't have a declaration.

Two ways to fix this:
At the top of act_wiz.c where you might see some other declarations of functions (things like:
extern void do_something args((char_data *ch, argument));

add the declarations for weather_update etc. in there with the others up there. You should be able to look around the code and see some stuff declared in a similar manner in order to figure out how to do this.

The other thing is go into merc.h and near the bottom there is a huge list of function declarations which have a commented file name above them (for example, the declarations for act_wiz.c is likely listed under /* act_wiz.c */ or something similar). Add those function declarations under the appropriate listing (I think update.c) and since merc.h is included in every file in the code, anywhere you need to use those functions should be declared.

If I understand it right, without those declarations, basically the MUD doesn't know what do to with running across those functions, because it has nothing to reference or point to in order to grab the appropriate code.
21 May, 2009, David Haley wrote in the 20th comment:
Votes: 0
Quote
If I understand it right, without those declarations, basically the MUD doesn't know what do to with running across those functions, because it has nothing to reference or point to in order to grab the appropriate code.

Well, it's the compiler, not the MUD, but yes, that's the idea. It's seeing that you're using a symbol that it doesn't know about, but is trying to proceed anyhow (trying to be "nice" or "convenient" I suppose). Later, during the link phase, it will try to find that symbol in the object files, matching the signature (return type & argument types). If it fails, it will complain about an undefined symbol.
0.0/20