I really don't care about which function I use. If its SetTime(), I'll advance the clock eight hours when the rest finishes. If its SetCalendar(), I'll just advance the day by one.
Modifié par Pstemarie, 12 août 2011 - 09:12 .
Modifié par Pstemarie, 12 août 2011 - 09:12 .
Modifié par Pstemarie, 12 août 2011 - 09:29 .
//::///////////////////////////////////////////////
//:: Name: x2_onrest
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
The generic wandering monster system
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: June 9/03
//:://////////////////////////////////////////////
//:: Modified By: Deva Winblood
//:: Modified Date: January 28th, 2008
//:://////////////////////////////////////////////
#include "x2_inc_restsys"
#include "x2_inc_switches"
#include "x3_inc_horse"
void main()
{
object oPC = GetLastPCRested();
object oMount;
if (!GetLocalInt(GetModule(),"X3_MOUNT_NO_REST_DISMOUNT"))
{ // make sure not mounted
/* Deva, Jan 17, 2008
Do not allow a mounted PC to rest
*/
if (HorseGetIsMounted(oPC))
{ // cannot mount
if (GetLocalInt(oPC,"X3_REST_CANCEL_MESSAGE_SENT"))
{ // cancel message already played
DeleteLocalInt(oPC,"X3_REST_CANCEL_MESSAGE_SENT");
} // cancel message already played
else
{ // play cancel message
FloatingTextStrRefOnCreature(112006,oPC,FALSE);
SetLocalInt(oPC,"X3_REST_CANCEL_MESSAGE_SENT",TRUE); // sentinel
// value to prevent message played a 2nd time on canceled rest
} // play cancel message
AssignCommand(oPC,ClearAllActions(TRUE));
return;
} // cannot mount
} // make sure not mounted
if (!GetLocalInt(GetModule(),"X3_MOUNT_NO_REST_DESPAWN"))
{ // if there is a paladin mount despawn it
oMount=HorseGetPaladinMount(oPC);
if (!GetIsObjectValid(oMount)) oMount=GetLocalObject(oPC,"oX3PaladinMount");
if (GetIsObjectValid(oMount))
{ // paladin mount exists
if (oMount==oPC||!GetIsObjectValid(GetMaster(oMount))) AssignCommand(oPC,HorseUnsummonPaladinMount());
else { AssignCommand(GetMaster(oMount),HorseUnsummonPaladinMount()); }
} // paladin mount exists
} // if there is a paladin mount despawn it
if (GetModuleSwitchValue(MODULE_SWITCH_USE_XP2_RESTSYSTEM) == TRUE)
{
/* Georg, August 11, 2003
Added this code to allow the designer to specify a variable on the module
Instead of using a OnAreaEnter script. Nice new toolset feature!
Basically, the first time a player rests, the area is scanned for the
encounter table string and will set it up.
*/
object oArea = GetArea (oPC);
string sTable = GetLocalString(oArea,"X2_WM_ENCOUNTERTABLE") ;
if (sTable != "" )
{
int nDoors = GetLocalInt(oArea,"X2_WM_AREA_USEDOORS");
int nDC = GetLocalInt(oArea,"X2_WM_AREA_LISTENCHECK");
WMSetAreaTable(oArea,sTable,nDoors,nDC);
//remove string to indicate we are set up
DeleteLocalString(oArea,"X2_WM_ENCOUNTERTABLE");
}
/* Brent, July 2 2003
- If you rest and are a low level character at the beginning of the module.
You will trigger the first dream cutscene
*/
if (GetLocalInt(GetModule(), "X2_G_LOWLEVELSTART") == 10)
{
AssignCommand(oPC, ClearAllActions());
if (GetHitDice(oPC) >= 12)
{
ExecuteScript("bk_sleep", oPC);
return;
}
else
{
FloatingTextStrRefOnCreature(84141 , oPC);
return;
}
}
/*
Pstemarie, 11 August 2011
Force the remaining party members to rest
*/
object oPartyMember = GetFirstFactionMember(oPC);
while(GetIsObjectValid(oPartyMember) == TRUE)
{
AssignCommand(oPartyMember, ClearAllActions());
SendMessageToPC(oPartyMember, "You rest with the other members of your party.");
//Check spellbook
if (GetLevelByclass(class_TYPE_WIZARD, oPartyMember) > 0)
{
if (GetItemPossessedBy(oPartyMember, "m1_it_spellbk001") == OBJECT_INVALID)
{
//Store pre-rest values for all memorized spells
int nSpell, nUses, nStored;
for (nSpell = 0; nSpell < 599; nSpell ++)
{
nUses = GetHasSpell(nSpell, oPC);
if (nUses > 0)
{
SetLocalInt(oPartyMember, IntToString(nSpell), nUses);
}
}
ForceRest(oPartyMember);
//Reset spells to their pre-rest values
for (nSpell = 0; nSpell < 599; nSpell ++)
{
nUses = GetHasSpell(nSpell, oPartyMember);
nStored = GetLocalInt(oPartyMember, IntToString(nSpell));
nStored = nUses - nStored;
for (nUses = 0; nUses < nStored; nUses ++)
{
DecrementRemainingSpellUses(oPartyMember, nSpell);
}
DeleteLocalInt(oPartyMember, IntToString(nSpell));
}
SendMessageToPC(oPartyMember, "You cannot regain spells without a spellbook.");
}
else
{
ForceRest(oPartyMember);
}
}
//Check spellbook
else
{
ForceRest(oPartyMember);
}
oPartyMember = GetNextFactionMember(oPC);
}
if (GetLastRestEventType()==REST_EVENTTYPE_REST_STARTED)
{
if (!WMStartPlayerRest(oPC))
{
// The resting system has objections against resting here and now
// Probably because there is an ambush already in progress
FloatingTextStrRefOnCreature(84142 ,oPC);
AssignCommand(oPC,ClearAllActions());
}
if (WMCheckForWanderingMonster(oPC))
{
//This script MUST be run or the player won't be able to rest again ...
ExecuteScript("x2_restsys_ambus",oPC);
}
//Check spellbook
/*
Pstemarie, 11 August 2011
Do not allow a wizard to regain spells without a spellbook
Step 1 - Store remaining uses for memorized spells
*/
if (GetLevelByclass(class_TYPE_WIZARD, oPC) > 0)
{
if (GetItemPossessedBy(oPC, "m1_it_spellbk001") == OBJECT_INVALID)
{
//Store pre-rest values for all memorized spells
int nSpell, nUses;
for (nSpell = 0; nSpell < 599; nSpell ++)
{
nUses = GetHasSpell(nSpell, oPC);
if (nUses > 0)
{
SetLocalInt(oPC, IntToString(nSpell), nUses);
}
}
}
}
//Check spellbook
}
else if (GetLastRestEventType()==REST_EVENTTYPE_REST_CANCELLED)
{
// No longer used but left in for the community
// WMFinishPlayerRest(oPC,TRUE); // removes sleep effect, etc
}
else if (GetLastRestEventType()==REST_EVENTTYPE_REST_FINISHED)
{
// No longer used but left in for the community
// WMFinishPlayerRest(oPC); // removes sleep effect, etc
//Check spellbook
/*
Pstemarie, 11 August 2011
Do not allow a wizard to regain spells without a spellbook
Step 2 - Reset remaining uses for memorized spells
*/
if (GetLevelByclass(class_TYPE_WIZARD, oPC) > 0)
{
if (GetItemPossessedBy(oPC, "m1_it_spellbk001") == OBJECT_INVALID)
{
//Reset spells to their pre-rest values
int nSpell, nUses, nStored;
for (nSpell = 0; nSpell < 599; nSpell ++)
{
nUses = GetHasSpell(nSpell, oPC);
nStored = GetLocalInt(oPC, IntToString(nSpell));
nStored = nUses - nStored;
for (nUses = 0; nUses < nStored; nUses ++)
{
DecrementRemainingSpellUses(oPC, nSpell);
}
DeleteLocalInt(oPC, IntToString(nSpell));
}
SendMessageToPC(oPC, "You cannot regain spells without a spellbook.");
}
}
//Check spellbook
//Advance game clock
/*
Pstemarie, 11 August 2011
Advance the game clock 8 hours when a player rests
*/
int nHour = GetTimeHour();
int nMin = GetTimeMinute();
int nSec = GetTimeSecond();
int nMSec = GetTimeMillisecond();
nHour += 8;
SetTime(nHour, nMin, nSec, nMSec);
//Advance game clock
}
}
}
Modifié par Pstemarie, 12 août 2011 - 10:14 .
Modifié par Axe_Murderer, 12 août 2011 - 10:23 .
Modifié par Pstemarie, 12 août 2011 - 10:47 .
Modifié par Axe_Murderer, 12 août 2011 - 10:53 .
Modifié par Pstemarie, 12 août 2011 - 12:48 .
Modifié par Pstemarie, 12 août 2011 - 02:43 .
Except it won't tick. The OnPlayerDying event only happens once. When you go below 1HP the engine fires either an OnDeath or an OnDying event depending on whether you made it all the way down to -10 or not . Only one event is generated. The effect your using is like a wounding effect. It automatically applies itself once per round and automatically removes itself when the player gets back above 0 or down to -10 (then the engine fires OnDeath).Pstemarie wrote...
Here you go ShaDoOoW. I just put the visual in there for a sort of "ticking" timer.
...
Modifié par Axe_Murderer, 12 août 2011 - 04:47 .
Re-executing is more efficient as recursive funtions keep stacking variables in memory or something like that, the more parameters in function the worse and definitely avoid structs in recursive functions. Anyway for small functions like this it shouldnt matter it has differences only when its huge script with many parameters repeating many times.henesua wrote...
Axe, is it more efficient to recursively call a function, or execute a script that calls itself? Are they the same?
I handled dying similarly in my mod, but instead of calling a function in my dying script, I executed a bleed script that iterates once a round. My thought was that the dying script and all its variables would remain in use until all the delays called within it were complete. Therefore for cleaner garbage collection, I thought executing a separate script would be more efficient - because the entire script would purge itself each time it executed.
Modifié par Axe_Murderer, 12 août 2011 - 09:51 .
Axe_Murderer wrote...
Except it won't tick. The OnPlayerDying event only happens once. When you go below 1HP the engine fires either an OnDeath or an OnDying event depending on whether you made it all the way down to -10 or not . Only one event is generated. The effect your using is like a wounding effect. It automatically applies itself once per round and automatically removes itself when the player gets back above 0 or down to -10 (then the engine fires OnDeath).Pstemarie wrote...
Here you go ShaDoOoW. I just put the visual in there for a sort of "ticking" timer.
...
If you were to use a regular damage effect there instead, the player would only get one application of it and then be forever incapacitated unless it was enough to kill him, or somebody comes along and heals him, or the module somehow decides he should be healed or killed and does so. That's why the WhenDying effect exists and why you apply it using a permanent duration and why you can't use it as a wounding effect on living creatures.
So your visual effect will only occur once at the start of bleeding.
To make a pulse effect to go along with it:
[nwscript]void PulseBlood()
{ if( GetIsDead( OBJECT_SELF ) || (GetCurrentHitPoints() > 0) ) return;
ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_COM_BLOOD_SPARK_SMALL ), OBJECT_SELF );
DelayCommand( RoundsToSeconds( 1 ), PulseBlood() );
}
void main()
{ object oPC = GetLastPlayerDying();
ApplyEffectToObject( DURATION_TYPE_PERMANENT, EffectHitPointChangeWhenDying( 1.0 ), oPC );
AssignCommand( oPC, PulseBlood() );
}[/nwscript]
Modifié par Pstemarie, 13 août 2011 - 10:15 .