View Full Version : Time Based Spell Bonuses
zerjz3
11-14-2014, 01:23 PM
I'm trying to set up time and weather based buffs that are automatically cast on the player as the time and weather change.
I'm starting simple, just to get a feel for how this is scripted and how it works, but the method seems to be eluding me.
Here's what I've got in the player.pl file in one zone currently, just to test it - when I have the script working, I'm gonna move it into global_player.pl
I've currently got this set to (when it's working) cast on the player every time they zone, but what I *really* want is for the daytime buff to cast when it hits daytime, last until night, and then the nighttime buff is cast and overwrites the daytime buff. But I'm starting small, just to get a grip on this.
sub EVENT_ENTERZONE{
if ($zonetime > 599 || $zonetime < 1900) {
quest::selfcast(11);
}
}
What am I doing wrong here?
rencro
11-14-2014, 03:30 PM
[quote]
sub EVENT_ENTERZONE{
if ($zonetime > 599 || $zonetime < 1900) {
quest::selfcast(11);
}
}
Your if statement will always be true regardless of the time.
zerjz3
11-14-2014, 04:31 PM
Why is that? How can I correct it?
lerxst2112
11-14-2014, 04:35 PM
To be more specific, you need to use logical and (&&) here instead of or.
rencro
11-14-2014, 05:23 PM
Something like:
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The time is right");
quest::selfcast(11);
}
else {
$client->Message(13, "Be very afraid of the dark");
}
zerjz3
11-14-2014, 07:13 PM
Thanks for the help, that works perfectly for sub EVENT_CONNECT but I cannot seem to get it working for sub EVENT_ZONE or sub EVENT_ENTERZONE sadly.
rencro
11-14-2014, 09:03 PM
I tested in tutorialb on player.pl in EVENT_ENTERZONE just fine, but my code is forked off of June 2014, though doubt that would make a difference ( i guess it could, but that would be bad if so)
Also, need to consider that you would need some kind of logic to turn the daytime buff off and replace with the nighttime version and vice versa, these would only run once (but as you said, start small) As for your final version may want to do it in the BuffProcees() function in zone/spell_effects.cpp although it could be done many ways I suppose in perl.
Ill try to put something like this together in c++ this weekend if I get the time (on-call for work, so no promises) I already do custom buffing ala eq2 in the BuffProcess() function myself.
As for your issues with EVENT_ENTERZONE, could you post your script for that? Curious why it works for me but not you (code differences notwithstanding)
zerjz3
11-14-2014, 09:20 PM
rencro, that would be FANTASTIC if you would take the time to code that for our server. I will indeed need some way to turn the daytime buff off and replace with the night buff, but hadn't gotten that far in my own thinking yet.
sub EVENT_ENTER_ZONE {
if (!defined $qglobals{$zonesn}) {
quest::gmsay("$name has discovered the zone $zoneln.", 335, 1, 0, 0);
quest::setglobal($zonesn, 1, 7, "F");
}
quest::settimer("Zoned", 5);
}
sub EVENT_TIMER {
if ($timer eq "Zoned") {
quest::stoptimer("Zoned");
if ($zonesn=~/Nexus/i && !defined $qglobals{"NexusBind"}) {
quest::selfcast(35);
quest::setglobal("NexusBind", 1, 5, "F");
}
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The time is right");
quest::selfcast(992);
} else {
$client->Message(13, "Be very afraid of the dark");
}
}
}
rencro
11-14-2014, 10:21 PM
You have an underscore between Enter and Zone, ie EVENT_ENTER_ZONE instead of EVENT_ENTERZONE more than likely from your testing going back and forth between settings.
zerjz3
11-15-2014, 12:20 PM
That fixed it, rencro! Thank you!
Now just to figure out how to make the night spell overwrite the day spell, and vice versa. Looking into this now!
zerjz3
11-15-2014, 12:46 PM
This is my first attempt at trying to cancel the daytime buff if the player zones and it is nighttime. Seems to have broken the entire script. Continuing to try and solve this...
sub EVENT_CONNECT {
quest::setlanguage(0, 100);
quest::setskill(40, 200);
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
} else {
$client->Message(13, "It's very dark outside.");
if($client->FindBuff(992));
$client->BuffFadeBySpellID(992);
}
}
sub EVENT_DISCOVER_ITEM {
quest::gmsay("$name has discovered the item " . quest::varlink($itemid) . ".", 335, 1, 0, 0);
}
sub EVENT_COMBINE_SUCCESS {
if (!defined $qglobals{$recipe_name}) {
quest::gmsay("$name has discovered the recipe for '$recipe_name'.", 335, 1, 0, 0);
quest::setglobal($recipe_name, 1, 7, "F");
}
}
sub EVENT_ENTERZONE {
if (!defined $qglobals{$zonesn}) {
quest::gmsay("$name has discovered the zone $zoneln.", 335, 1, 0, 0);
quest::setglobal($zonesn, 1, 7, "F");
}
quest::settimer("Zoned", 5);
}
sub EVENT_TIMER {
if ($timer eq "Zoned") {
quest::stoptimer("Zoned");
if ($zonesn=~/Nexus/i && !defined $qglobals{"NexusBind"}) {
quest::selfcast(35);
quest::setglobal("NexusBind", 1, 5, "F");
}
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down");
quest::selfcast(992);
} else {
$client->Message(13, "It's very dark outside.");
if($client->FindBuff(992));
$client->BuffFadeBySpellID(992);
}
}
}
Attempt 2
sub EVENT_CONNECT {
quest::setlanguage(0, 100);
quest::setskill(40, 200);
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
} elsif ($zonetime < 599 && $zonetime > 1900) {
$client->Message(13, "It's very dark outside.");
if($client->FindBuff(992));
$client->BuffFadeBySpellID(992);
}
}
Attempt 3... if someone could gently nudge me in the right direction (or crudely beat me over the head with it) that would be awesome..
sub EVENT_TIMER {
if ($timer eq "Zoned") {
quest::stoptimer("Zoned");
if ($zonesn=~/Nexus/i && !defined $qglobals{"NexusBind"}) {
quest::selfcast(35);
quest::setglobal("NexusBind", 1, 5, "F");
}
if ($zonetime > 599 && $zonetime < 1900) { #between 6am and 7pm
$client->Message(12, "The sun's rays beam down");
quest::selfcast(992);
}
if ($zonetime < 599 && $zonetime > 1900) { #between 7pm and 6am
$client->Message(13, "It's very dark outside.");
}
}
}
I should note that in this last attempt I am simply trying to change the night time message to trigger in a different fashion so I can then insert the buff removal code once I see that it's checking a specific time and not just going by an else statement
zerjz3
11-15-2014, 01:51 PM
sub EVENT_CONNECT {
quest::setlanguage(0, 100);
quest::setskill(40, 200);
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
}
elsif ($zonetime < 599 && $zonetime > 1900) { #night
$client->Message(13, "It's very dark outside.");
}
}
sub EVENT_DISCOVER_ITEM {
quest::gmsay("$name has discovered the item " . quest::varlink($itemid) . ".", 335, 1, 0, 0);
}
sub EVENT_COMBINE_SUCCESS {
if (!defined $qglobals{$recipe_name}) {
quest::gmsay("$name has discovered the recipe for '$recipe_name'.", 335, 1, 0, 0);
quest::setglobal($recipe_name, 1, 7, "F");
}
}
sub EVENT_ENTERZONE {
if (!defined $qglobals{$zonesn}) {
quest::gmsay("$name has discovered the zone $zoneln.", 335, 1, 0, 0);
quest::setglobal($zonesn, 1, 7, "F");
}
quest::settimer("Zoned", 5);
}
sub EVENT_TIMER {
if ($timer eq "Zoned") {
quest::stoptimer("Zoned");
if ($zonesn=~/Nexus/i && !defined $qglobals{"NexusBind"}) {
quest::selfcast(35);
quest::setglobal("NexusBind", 1, 5, "F");
}
if ($zonetime > 599 && $zonetime < 1900) { #day
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
}
elsif ($zonetime < 599 && $zonetime > 1900) { #night
$client->Message(13, "It's very dark outside.");
}
}
}
rencro
11-15-2014, 01:58 PM
You shoulnd't need to do another time compare because if its not daytime, then an else means its gotta be dark
On attempt two, there is an error with the if statement
sub EVENT_CONNECT {
quest::setlanguage(0, 100);
quest::setskill(40, 200);
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
} else {
$client->Message(13, "It's very dark outside.");
if($client->FindBuff(992));
$client->BuffFadeBySpellID(992);
}
}
Need the { } brackets to process this if statement
sub EVENT_CONNECT {
quest::setlanguage(0, 100);
quest::setskill(40, 200);
if ($zonetime > 599 && $zonetime < 1900) {
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992);
} else {
$client->Message(13, "It's very dark outside.");
if($client->FindBuff(992)){
$client->Message(13, "Its dark and you have the daytime buff, so nighty night buff");
$client->BuffFadeBySpellID(992);
} else {
$client->Message(13, "Its night, but you dont have the daytime buff");
}
}
}
Something like that, didnt actually test this in player.pl but on arias, but should be ok as long as I got all the brackets right/ Also you can ignore the messages or remove them I just use them for troubleshooting
zerjz3
11-15-2014, 02:24 PM
Thank you! Got it working now, and now I understand WHY and HOW it works, most importantly!
rencro
11-15-2014, 02:34 PM
I'm testing this is both BuffProcess and in BuffTic by creating a new SE_TimeOfDayBuff, not sure which would be better but this could all be done from perl by I guess having a timer constantly running on player zonein that checks the status of the buff on said player and, if the time changes while they are still in zone, to fade one and apply the other. Just dont know how "expensive" that would be having all these timers running in perl. Maybe Kingly Krab or Akka can chime in and help you there, as they definitely have perl grasped far better than I.
But Im intrigued by this idea and will keep working on it in c++. The problem if you apply a c++ solution is you will have to maintain(merge) it any time you decide to upgrade the server source.
zerjz3
11-15-2014, 02:41 PM
I have done a few source code edits of my own, so that would need to be done (the merging) anyhow, when the time comes to upgrade the server source.
I was myself puzzling over how to implement a "live" time change switch, like you mentioned, instead of just triggering on zoning.
Incidentally, I have managed to break this script again, by trying to reverse what we coded and cancel out the night time buff when it's day time. I will highlight the area I think caused the problem, and explain why I think it happened.
sub EVENT_TIMER {
if ($timer eq "Zoned") {
quest::stoptimer("Zoned");
if ($zonesn=~/Nexus/i && !defined $qglobals{"NexusBind"}) {
quest::selfcast(35);
quest::setglobal("NexusBind", 1, 5, "F");
}
if ($zonetime > 599 && $zonetime < 1900) { #it is day time
if($client->FindBuff(346)){ #find night buff
$client->Message(12, "The darkness wanes.");
$client->BuffFadeBySpellID(346); #cancel night buff
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(992); #cast day buff
} else { #does not have night buff
quest::selfcast(992);
} else { #it is night time
$client->Message(12, "It's very dark outside.");
if($client->FindBuff(992)){ #find day buff
$client->Message(12, "The sunlight fades.");
$client->BuffFadeBySpellID(992); #cancel day buff
quest::selfcast(346); #cast night buff
} else { #does not have the day buff
quest::selfcast(346); #cast night buff
}
}
}
}
}
I believe this happened because we've kept the night check as just an "else" statement and not actually coded in the times that it considers to be night, so when I added another "else" in there, it's getting confused about what's actually going on. This is why I thought we needed to actually designate the specific times of night, instead of just going by "else" --- does that make sense, and am I correct in thinking this is what caused the problem?
rencro
11-15-2014, 03:39 PM
Here is your script edited for Arias, I have used spellid 11 as the day buff. Putting this back into .pl will be almost identical.
if ($text=~/timebuff/i) {
if ($zonetime > 599 && $zonetime < 1900) { #it is day time
if($client->FindBuff(346)){ #find night buff
$client->Message(12, "The darkness wanes.");
$client->BuffFadeBySpellID(346); #cancel night buff
}
$client->Message(12, "The sun's rays beam down.");
quest::selfcast(11); #cast day buff
} else { #it is night time
$client->Message(12, "It's very dark outside.");
if($client->FindBuff(11)){ #find day buff
$client->Message(12, "The sunlight fades.");
$client->BuffFadeBySpellID(11); #cancel day buff
}
quest::selfcast(346); #cast night buff
}
}
The extra else statements were an issue as well placement of some commands. The casting of the nightime buff at night only needs to be processed once, outside of the "check for daytime buff IF" and vice versa. Does that make sense? For instance we are doing
quest::selfcast(346); #cast night buff
but we are still in the "else" day/night check, but are outside of the "if has daytime buff check, which is also part of the else daytime/nightime check"
Sorry, i suck at explaining things.
Also, in this case you will get a message that it is dark, then a message that the sun fades, so if you would want this switched then just move the its very dark outside messaage to after the check for daytime buff and vice versa.
zerjz3
11-15-2014, 03:52 PM
rencro, you got it! This one works exactly as I wanted it to! Would still love to get it working in a "live" manner, as in automatically firing when the right times hit, but I'm more than happy with its current implementation! Maybe Kingly will know how to get it to update itself automatically without needing to zone.
Edit: I'm thinking about this, and my guess is that timers would somehow be involved in making this update itself without the need to zone.........
rencro
11-15-2014, 04:28 PM
Actually you did it, this is your code, I just helped a bit with the formatting. This could get silly complicated depending how far you want to push this idea. For instance if its nightime and the class in Necro, do they get a boost buff, where as if its a paladin do they get maybe a slight debuff.
Also, if its daytime and it starts to rain, do the day buffs get halved, and do druids get a silly powerfull storm buff, also what happens when inside a dungeon, I assume you would negate the system altogether but the choice is yours. ect ect ect, lots of places to take this.
I'll post the c++ code sometime soon, just want to play with different setting ect first.
zerjz3
11-15-2014, 04:32 PM
Awesome! That's my ultimate plan, to make this into a very complex and robust Time and Weather System. I just wanted to start small so I could get a handle on how this would be working in practice. Theories, I have many, but putting them into practice is where I sometimes have trouble :)
Next I am going to be looking into the DayNight npcs and DayNight.pl in quest globals to find a way to make this update itself automatically when the time of day changes.
Once I have a more robust version of this, with weather effects and such, I will be posting it for others who are interested in doing something like this with their servers.
zerjz3
11-15-2014, 06:54 PM
Edit: Nevermind!
rencro
11-15-2014, 10:46 PM
Here is what i have so far, I built this on my fork, and tested, but a diff from my fork would be useless so I imported into the latest source after doing a diff between my source and the latest (not too many changes, and nothing I think that would cause any issues) Note, I did not build or test this on the current live source even though it is diffed against it.
I cannot stress enough to create a branch of your source, patch this in, and build on a TEST ENVIRONMENT, not your production server, also that test environment should be using a COPY of your production database, not the actual production db itself (sorry if I seem overly anal, but I assisted a server op before with the same provisos, and to thoroughly test my changes, and he told me he would, but he went live with it 5 minutes later :???: and there were countless bugs as a result affecting the live players :facepalm
Rant over
diff current source
diff --git a/common/spdat.cpp b/common/spdat.cpp
index 1ff8f26..8579f61 100644
--- a/common/spdat.cpp
+++ b/common/spdat.cpp
@@ -1146,3 +1146,39 @@ const char* GetSpellName(int16 spell_id)
return spells[spell_id].name;
}
+// rencro timeofday buff, both day and night buffs are listed here
+bool IsTimeOfDayBuff(int16 spell_id)
+{
+ switch(spell_id)
+ {
+ case 346:
+ case 992:
+// case 11: //rencro temp testing
+// case ###:
+ return true;
+ }
+ return false;
+}
+//rencro daytime buffs only
+bool IsDayTimeBuff(int16 spell_id)
+{
+ switch(spell_id)
+ {
+ case 992:
+// case 11: //rencro testing purposes only
+// case ###:
+ return true;
+ }
+ return false;
+}
+//rencro nightime buffs only
+bool IsNightTimeBuff(int16 spell_id)
+{
+ switch(spell_id)
+ {
+ case 346:
+// case ###:
+ return true;
+ }
+ return false;
+}
\ No newline at end of file
diff --git a/common/spdat.h b/common/spdat.h
index ed8a86e..7cd1e00 100644
--- a/common/spdat.h
+++ b/common/spdat.h
@@ -874,5 +874,8 @@ int32 GetFuriousBash(uint16 spell_id);
bool IsShortDurationBuff(uint16 spell_id);
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
const char *GetSpellName(int16 spell_id);
+bool IsTimeOfDayBuff(int16 spell_id); //rencro
+bool IsDayTimeBuff(int16 spell_id); //rencro
+bool IsNightTimeBuff(int16 spell_id); //rencro
#endif
diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp
index 447d34e..c63d109 100644
--- a/zone/spell_effects.cpp
+++ b/zone/spell_effects.cpp
@@ -3360,8 +3360,45 @@ void Mob::BuffProcess()
// If the Mob died during DoBuffTic, then the buff we are currently processing will have been removed
if(buffs[buffs_i].spellid == SPELL_UNKNOWN)
continue;
+ //rencro Time of Day Buffing
+ if(IsClient() && IsTimeOfDayBuff(buffs[buffs_i].spellid))
+ {
+ TimeOfDay_Struct eqTime;
+ zone->zone_time.getEQTimeOfDay( time(0), &eqTime);
+
+ if(eqTime.hour > 6 && eqTime.hour < 20) // eqTime.hour -1 is proper formula, we are checking greater than 5am less than 7pm
+ {
+ //Message(13, "We are in daylight"); //troubleshooting message
+ if(IsNightTimeBuff(buffs[buffs_i].spellid))
+ {
+ Message(12, "The sun's rays beam down.");
+ BuffFadeBySlot(buffs_i);
+ CastSpell(992, GetID(), 1,0,0); //cast spell the day spell with no mana cost and no cast time
+ }
+ //leaving this if daytime check for when weather checks get added in
+ if(IsDayTimeBuff(buffs[buffs_i].spellid))
+ {
+// Message(11, "I have a daytime buff on"); //troubleshooting message
+ }
- if(spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent)
+ } else
+ {
+// Message(13, "We are in the dark"); //troubleshooting message
+ if(IsDayTimeBuff(buffs[buffs_i].spellid))
+ {
+ Message(12, "The sunlight fades");
+ BuffFadeBySlot(buffs_i);
+ CastSpell(346, GetID(), 1,0,0); //cast spell grim aura the night spell with no mana cost, no cast time
+ }
+ //leaving this here in case of future weather adjustments at night
+ if(IsNightTimeBuff(buffs[buffs_i].spellid))
+ {
+// Message(11, "I have a Nighttime buff on"); //troubleshootinmg message
+ }
+ }
+ }
+ //rencro done with timeofday stuff
+ else if(spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent)
{
if(!zone->BuffTimersSuspended() || !IsSuspendableSpell(buffs[buffs_i].spellid))
{
I had experimented with creating a custom spell effect, this would allow you to remove any of the buffs via perl BuffFadeByEffect(), and also have control over stacking, as well as easy implementation into the use of the DoBuffTic function. I left those out.
All this does is check if any of these buffs are active, and if its active during the wrong time-frame to remove it and put the relevant version on. You still need to turn the relevant buff on via perl for this to do the checks on.
I made this to where it is easily expandable, can add more spells in, do compares of day buffs during the day ect ect. Also, please anyone, feel free to tell me where this can be improved ect..
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.