generated from Jaysyn/ModuleTemplate
672 lines
27 KiB
Plaintext
672 lines
27 KiB
Plaintext
// Henchmen Always Bleed to Death
|
|
// By Demtrious, OldManWhistler and IntrepidCW
|
|
//
|
|
// PLEASE READ "habd_include" FOR MORE INFORMATION.
|
|
//
|
|
// OnPlayerRespawn event handler.
|
|
|
|
/* Clarifications about HABD states:
|
|
NWN original has only Two states: Death (-10 or less hps), Dying (0 to -10 hps),
|
|
and Alive (0+ hps). But death and dying are similar: you are out.
|
|
HABD 'fakes' a new state and changes the rules, we have 5 states: Alive - Bleeding
|
|
- Death -Respawn -Permadeath
|
|
For NWN, HABD_Alive and HABD_Respawn are 'alive'. HABD_Bleeding is NWN Dying
|
|
and HABD_Death is NWN Death.
|
|
In this order, a player starts Alive. Then he drops to Bleeding and triggers the
|
|
OnDying Event. He could drop to Death after Instant Kill or after Bleeding.
|
|
When Death the PC remains on the ground until Respawned. Respawned is NOT Alive
|
|
, respawned is the state of a Ghost or a PC soul that can not leave a 'Hell'
|
|
area. When Raised, the PC becomes really Alive.
|
|
*/
|
|
|
|
/* Notes about JumpToLocation (important if you modify this code)
|
|
JumptoLocation Does not affect creatures that are dead; they must have HP above
|
|
0 for this function to work properly.
|
|
Unfortunatelly the Effect Heal is not instantaneous... healing needs some time,
|
|
and what is worst, this time depends of the amount of hps to be healed.
|
|
It is often needed to call ClearAllActions() to use jumptoloc.
|
|
More important, if you set the PC NOT comandable, just after calling the Jump it
|
|
will not work, you must delay a bit the set commandable FALSE.
|
|
Some things cannot be done when the player travels to another area, as working
|
|
with inventory or equipment.
|
|
*/
|
|
#include "x0_i0_henchman"
|
|
#include "habd_include"
|
|
|
|
// Change this value if it is causing server lag.
|
|
// Ghost processes (check status, follow master, etc..) are done only when
|
|
// GHOST_LOOP_TIMER seconds have passed (repeteadly). Less than 6 seconds will
|
|
// make it more fluid, but most CPU costly (and maybe laggy).
|
|
const float GHOST_LOOP_TIMER = 6.0f;
|
|
|
|
// ****************************************************************************
|
|
|
|
// Set to TRUE to activate the function HABDUserDefinedRespawnFinished, otherwise
|
|
// it will never run.
|
|
const int USE_RespawnFinished_Function = FALSE;
|
|
// USER DEFINED FUNCTION
|
|
// When called, we are sure the PC is an Area (not jumping to another), and set
|
|
// to NOT commandable, with PlotFlag. If you make he commandable or NO-Plot,
|
|
// you should return to not commandable and Plot at the end of the script.
|
|
// If you use jumping to a 'hell' i counsel to use a script in OnEnter of the
|
|
// Hell Area, because someone closing the NWN Client when moving to another
|
|
// area could cause a problem.
|
|
// Furthermore, we are sure the rest of the respawn script is finished.
|
|
void HABDUserDefinedRespawnFinished(object oPC)
|
|
{
|
|
|
|
}
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
// :: PERMADEATH :: CUSTOM FUNCTION :: MODIFY TO CONFIGURE PERMADEATH //
|
|
int HABDUserDefinedPermadeath( object oPC)
|
|
{
|
|
/* You MUST script the conditions that lead to permadeath AND the effects of
|
|
PERMADEATH (some effects should be better scripted in the respawn script).
|
|
Take in mind that this function is called from the RESPAWN script.
|
|
This function MUST return TRUE or FALSE. True if it is permadeath, False if no
|
|
permadeath. Note that, when returning true, the respawn script will no longer
|
|
run, and no respawn effect/penalties will be applied.
|
|
Note: habd_utils, has code for a raising portal that raises Permadeath PCs, as a
|
|
safety measure you can place the portal in a Non-accesible part of the area...
|
|
or into a DM exclusive use area.
|
|
*/
|
|
int iPermadeath = FALSE;
|
|
object oMod = GetModule();
|
|
string sID = GetPCPlayerName(oPC)+GetName(oPC);
|
|
//usefull player stats that help to determine when we apply permadeath.
|
|
int DeathCount = GetLocalInt(oMod, HABD_DEATH_COUNT+sID); //number of times the PC has died
|
|
//int BleedCount = GetLocalInt(oMod, HABD_BLEED_COUNT+sID); //idem with bleeding
|
|
//int LostXPCount = GetLocalInt(oMod, HABD_LOST_XP_COUNT+sID); //Total XP lost
|
|
//int LosGPCount = GetLocalInt(oMod, HABD_LOST_GP_COUNT+sID); //Total GP lost
|
|
//int PCLevel = GetHitDice (oPC);
|
|
//int PC_Con = GetAbilityScore(oPC, ABILITY_CONSTITUTION);
|
|
//int PC_AloneInArea = HABDPlayerAloneInArea(oPC);
|
|
|
|
//Now, script the condition that drops the player to Permadeath.
|
|
// if ( DeathCount > 3*PCLevel ) { iPermadeath = TRUE; } //example
|
|
|
|
/* //correct negative hitpoints reached when you died due to instant death
|
|
if (GetLocalInt(GetModule(), HABD_MINHPLASTBLEED+sID)<=-30)
|
|
{ iPermadeath = TRUE; } //example
|
|
*/
|
|
|
|
//The custom-use variable can help you to script complex and persistent
|
|
//permadeath effects and conditions
|
|
// string scvar = HABDGetCustomVar(oPC);
|
|
// if (PCLevel >10) HABDSetCustomVar(oPC, "Permadeath_Hell_N10"); //example
|
|
|
|
//No Permadeath
|
|
if ( iPermadeath == FALSE )
|
|
return FALSE;
|
|
//PERMADEATH !!!!
|
|
else
|
|
{
|
|
SendMessageToPC(oPC, "OOC: Permadeath. Moving to Fugue Plane.");
|
|
HABDSetHABD_PLAYER_STATE(HABD_STATE_PC_PERMADEATH, sID, oPC);
|
|
HABDApplyPenalty(oPC, HABD_RESPAWN_XP_LOSS, HABD_RESPAWN_GP_LOSS, HABD_EVENTRESPAWNSIGNAL);
|
|
//Save info to DB (and maybe export PC) to avoid server crash problems,
|
|
//now that we are sure the PC is Permadeath.
|
|
if ( HABD_SMART_SAVETODB == TRUE )
|
|
HABDSetDBString(oPC);
|
|
SetCommandable(TRUE, oPC);
|
|
// "Raise" the player (only effect), MANDATORY!!
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oPC);
|
|
HABDJumpToPermaDeathPoint(oPC);
|
|
return TRUE;
|
|
}
|
|
}
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
// This function acts as a player heartbeat while the player is under the
|
|
// "respawn effect".
|
|
// oOldFollow - is the last object the player was told to follow.
|
|
|
|
void Ghost(object oOldFollow = OBJECT_INVALID)
|
|
{
|
|
object oMod = GetModule();
|
|
object oPC = OBJECT_SELF;
|
|
string sID = GetPCPlayerName(oPC)+GetName(oPC);
|
|
//DEBUG: Not translated to spanish
|
|
if (HABD_DEBUG) SpeakString("DEBUG: HABD OnGhostHB, "+GetName(oPC)+", PlotFlag:"+IntToString(GetPlotFlag(OBJECT_SELF))+", CommandableFlag:"+IntToString(GetCommandable())+", HP: "+IntToString(GetCurrentHitPoints(oPC))+", master: "+GetName(GetMaster(oPC))+", state:"+HABDGetPlayerStateName(oPC), TALKVOLUME_SHOUT);
|
|
|
|
int iState = HABDGetHABD_PLAYER_STATE(sID, oPC);
|
|
|
|
if (
|
|
(GetPlotFlag(OBJECT_SELF)) &&
|
|
(iState == HABD_STATE_RESPAWNED_GHOST)
|
|
)
|
|
{
|
|
// Is there someone to follow?
|
|
object oFollow = GetLocalObject(oPC, HABD_GHOST_AUTOFOLLOW);
|
|
HABDAssociateBusy();
|
|
SetCommandable(TRUE);
|
|
// Most important, schedule the next iteration of the heartbeat.
|
|
DelayCommand(GHOST_LOOP_TIMER, Ghost(oFollow));
|
|
if (GetIsObjectValid(oFollow))
|
|
{
|
|
if (oFollow != oOldFollow) FloatingTextStringOnCreature(GetName(OBJECT_SELF)+" is now following "+ GetName(oFollow), oPC, TRUE);
|
|
if (GetArea(OBJECT_SELF) != GetArea(oFollow))
|
|
{
|
|
if ( HABD_GHOST_COMMANDABLE == FALSE)
|
|
{
|
|
if(HABD_USERLANGUAGE==0)
|
|
SendMessageToPC(oPC, "Jumping to "+GetName(oFollow));
|
|
else if(HABD_USERLANGUAGE==1)
|
|
SendMessageToPC(oPC, "Saltando hacia "+GetName(oFollow));
|
|
// Not in same area, jump them there
|
|
ClearAllActions();
|
|
ActionJumpToObject(oFollow);
|
|
}
|
|
} else {
|
|
// In same area, move them there
|
|
ClearAllActions();
|
|
DelayCommand(0.5, ActionForceFollowObject(oFollow, 6.0f));
|
|
}
|
|
}
|
|
// Apply effects to make them a ghost.
|
|
// Don't set the concealment too high just incase they find a way to abuse the system.
|
|
effect eBad = EffectConcealment(1);
|
|
eBad = EffectLinkEffects(EffectVisualEffect(VFX_DUR_PROT_SHADOW_ARMOR), eBad);
|
|
eBad = EffectLinkEffects(EffectVisualEffect(VFX_DUR_GHOSTLY_VISAGE), eBad);
|
|
if ( HABD_GHOST_EFFECTS_ON == TRUE)
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBad, oPC, GHOST_LOOP_TIMER+2.0f);
|
|
// Remove their ability to control themselves
|
|
if ( HABD_GHOST_COMMANDABLE == FALSE)
|
|
SetCommandable(FALSE);
|
|
}
|
|
else
|
|
// make sure that the ghost effects on/off doesnot raise players -avoid
|
|
// the exploit caused by using the PlotFag as condition (see the if conds)
|
|
if ( HABD_GHOST_EFFECTS_ON==TRUE || iState != HABD_STATE_RESPAWNED_GHOST )
|
|
{
|
|
HABDFinishRespawnGhost(oPC);
|
|
}
|
|
}
|
|
|
|
// ****************************************************************************
|
|
|
|
// This function checks that the player is not jumping to another area, it will
|
|
// trigger a function HABDUserDefinedRespawnFinished when finished the travel.
|
|
// It makes sure that we are in known circunstances.
|
|
|
|
void CheckGhostIsJumping(object ofPC)
|
|
{
|
|
if ( GetArea(ofPC)!= OBJECT_INVALID )
|
|
HABDUserDefinedRespawnFinished(ofPC);
|
|
else
|
|
DelayCommand(0.1,CheckGhostIsJumping(ofPC));
|
|
}
|
|
// ***************************************************************************
|
|
|
|
|
|
// This function checks that the player is not jumping to another area, it will
|
|
// make the player jump to the respawn point when finished the travel. It fixes
|
|
// some problems when jumping when we come from persistence.
|
|
void JumpToRespawnPoint(object oPC)
|
|
{
|
|
if ( GetArea(oPC) != OBJECT_INVALID )
|
|
{
|
|
if ( HABDRespawnWPTag(oPC) != "")
|
|
{
|
|
object oRespPoint = GetWaypointByTag(HABDRespawnWPTag(oPC));
|
|
if ( GetIsObjectValid (oRespPoint) ) //check the waypoint existes
|
|
{
|
|
location lRespLoc = GetLocation( oRespPoint );
|
|
SetCommandable(TRUE, oPC); //make sure the PC is commandable to jump
|
|
if (GetCurrentHitPoints(oPC)<=0)
|
|
{
|
|
effect eHealto1HP = EffectHeal(1-GetCurrentHitPoints(oPC));
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHealto1HP , oPC );
|
|
}
|
|
AssignCommand (oPC,ClearAllActions(TRUE));
|
|
AssignCommand (oPC, JumpToLocation (lRespLoc) );
|
|
DelayCommand ( 0.001, SetCommandable(FALSE, oPC) );
|
|
}
|
|
}
|
|
}
|
|
else DelayCommand ( 1.0, JumpToRespawnPoint(oPC) );
|
|
}
|
|
// ***************************************************************************
|
|
|
|
|
|
//searchs the nearest DeathBag of the PC
|
|
object SearchDeathBag(object oPC);
|
|
object SearchDeathBag(object oPC)
|
|
{
|
|
object oBag = OBJECT_INVALID;
|
|
int i=1;
|
|
oBag = GetNearestObjectByTag(HABD_PLACEABLE_BAG, oPC, i);
|
|
while ( oBag!=OBJECT_INVALID && i>0)
|
|
{
|
|
oBag = GetNearestObjectByTag(HABD_PLACEABLE_BAG, oPC, i);
|
|
if ( GetLocalObject(oBag, HABD_BAG_OWNER) == oPC )
|
|
i = -1000;
|
|
else
|
|
i=i+1;
|
|
}
|
|
return oBag;
|
|
}
|
|
|
|
|
|
//Creates the miscelaneous item Corpse of the oPC, into the object oBag Inventory,
|
|
//or the location lDrop if oBag is INVALID or is not found.
|
|
//oPC must be logged in!!
|
|
object CreateCorpse (object oPC, location lDrop, object oBag = OBJECT_INVALID );
|
|
object CreateCorpse (object oPC, location lDrop, object oBag = OBJECT_INVALID )
|
|
{
|
|
object corpse = OBJECT_INVALID;
|
|
string sResRef = "";
|
|
if( GetGender(oPC) == GENDER_FEMALE )
|
|
sResRef = HABD_CORPSEITEM_FEM_RESREF;
|
|
else
|
|
sResRef = HABD_CORPSEITEM_MALE_RESREF;
|
|
|
|
string sID = GetPCPlayerName(oPC) + GetName(oPC);
|
|
|
|
if (oBag != OBJECT_INVALID)
|
|
{
|
|
//create item on the bag
|
|
corpse = CreateItemOnObject(sResRef, oBag, 1);
|
|
//store info in the corpse
|
|
SetLocalString(corpse, HABD_CORPSE_OWNER_PLAYERNAME, GetPCPlayerName(oPC) );
|
|
SetLocalString(corpse, HABD_CORPSE_OWNER_PCNAME, GetName(oPC) );
|
|
}
|
|
else
|
|
{
|
|
//create item on the location
|
|
corpse = CreateObject(OBJECT_TYPE_ITEM, sResRef, lDrop);
|
|
//store info in the corpse
|
|
SetLocalString(corpse, HABD_CORPSE_OWNER_PLAYERNAME, GetPCPlayerName(oPC) );
|
|
SetLocalString(corpse, HABD_CORPSE_OWNER_PCNAME, GetName(oPC) );
|
|
}
|
|
//store in the PC, the corpse item object ID, it will help us to delete the
|
|
//corpse when the PC is raised
|
|
if (corpse != OBJECT_INVALID)
|
|
{
|
|
SetLocalObject(GetModule(), HABD_PC_CORPSE_OBJECT_ID + sID, corpse);
|
|
}
|
|
return corpse;
|
|
}
|
|
// ***************************************************************************
|
|
|
|
|
|
// OnPlayerRespawn event handler.
|
|
|
|
void main()
|
|
{
|
|
// Check to see if the system is supposed to run this script, otherwise
|
|
// it may be configured improperly.
|
|
if (HABD_RESPAWN_SCRIPT != "habd_onpcrespawn")
|
|
{
|
|
ExecuteScript(HABD_RESPAWN_SCRIPT, OBJECT_SELF);
|
|
return;
|
|
}
|
|
|
|
object oPC; //lets see who is the death guy
|
|
// Catch if the script was forced to executed.
|
|
// usually when coming from persistence, or timeforced respawn
|
|
if (GetLocalInt(OBJECT_SELF, HABD_FORCED_RESPAWN) == 1)
|
|
{
|
|
oPC = OBJECT_SELF;
|
|
HABDAssociateBusy();
|
|
} else {
|
|
oPC = GetLastRespawnButtonPresser();
|
|
}
|
|
|
|
object oMod = GetModule();
|
|
string sID = GetPCPlayerName(oPC)+GetName(oPC);
|
|
//DEBUG: Not translated to Spanish
|
|
if (HABD_DEBUG) SpeakString("DEBUG: HABD OnRespawn, "+GetName(oPC)+", HP: "+IntToString(GetCurrentHitPoints(oPC))+", master: "+GetName(GetMaster(oPC))+", state:"+HABDGetPlayerStateName(oPC), TALKVOLUME_SHOUT);
|
|
|
|
//Dinamically change the Respawn configuration, when the PC is carrying
|
|
//some special items
|
|
object oDinamicItem = OBJECT_INVALID;
|
|
int Dinamic = 0;
|
|
if (HABD_DINAMICRESPAWN1!=0)
|
|
{
|
|
int iolddinamic = GetLocalInt(oPC,HABD_DINAMIC_OPTION1);
|
|
//if no item is found, config variable is reset to 0
|
|
oDinamicItem = HABDSetDinamicRespawnByItem(oPC,0);
|
|
Dinamic = GetLocalInt(oPC,HABD_DINAMIC_OPTION1);
|
|
if (HABD_DINAMICRESPAWN1==2)
|
|
if (oDinamicItem!= OBJECT_INVALID)
|
|
DestroyObject(oDinamicItem);
|
|
}
|
|
|
|
// CHECK FIRST IF IT IS PERMADEATH
|
|
if ( HABDUserDefinedPermadeath(oPC) == TRUE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the player state to respawn.
|
|
HABDSetHABD_PLAYER_STATE(HABD_STATE_RESPAWNED_GHOST, sID, oPC);
|
|
|
|
// Make it look like something happened.
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_DOOM), oPC);
|
|
// Raise the player (only effect)
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oPC);
|
|
|
|
// Most important, schedule the ghost heartbeat.
|
|
AssignCommand(oPC, DelayCommand(3.0, Ghost()));
|
|
|
|
// If they have a master, set up the master as the autofollow.
|
|
if (GetIsObjectValid(GetMaster(oPC))) SetLocalObject(oPC, HABD_GHOST_AUTOFOLLOW, GetMaster(oPC));
|
|
else
|
|
{
|
|
// Remove any old autofollow objects.
|
|
DeleteLocalObject(oPC, HABD_GHOST_AUTOFOLLOW);
|
|
}
|
|
|
|
// Apply the user defined effects.
|
|
AssignCommand(oPC, HABDUserDefinedRespawn());
|
|
|
|
// Check if we are re-entering this state from persistence.
|
|
if (GetLocalInt(oPC, HABD_PERSISTANT_REAPPLY) != 1)
|
|
{
|
|
//determine the penalty to be applied
|
|
int xp_penalty = HABD_RESPAWN_XP_LOSS;
|
|
int gp_penalty = HABD_RESPAWN_GP_LOSS;
|
|
//Bindstone Respawn feature
|
|
if (HABD_BINDSTONE_USEWHENRESPAWNED == TRUE
|
|
&& HABD_BINDSTONE_RESPAWNPENALTY == TRUE)
|
|
{
|
|
object oBWP = HABDGetBindStoneWP(oPC);
|
|
int i = 0;
|
|
i = GetLocalInt(oBWP, HABD_BINDSTONEWP_XPPENALTY);
|
|
if ( i != 0)
|
|
{
|
|
if (i<0) xp_penalty = 0;
|
|
else xp_penalty = i;
|
|
}
|
|
i = GetLocalInt(oBWP, HABD_BINDSTONEWP_GPPENALTY);
|
|
if ( i != 0)
|
|
{
|
|
if (i<0) gp_penalty = 0;
|
|
else gp_penalty = i;
|
|
}
|
|
}
|
|
//Dinamic config feature
|
|
if (HABD_DINAMICRESPAWN1!=0)
|
|
if ( Dinamic>0 )
|
|
{
|
|
xp_penalty = HABDDinamicRespawnXP(Dinamic, xp_penalty);
|
|
gp_penalty = HABDDinamicRespawnGP(Dinamic, gp_penalty);
|
|
}
|
|
|
|
// Apply the respawn penalty.
|
|
HABDApplyPenalty(oPC, xp_penalty, gp_penalty, HABD_EVENTRESPAWNSIGNAL);
|
|
}
|
|
|
|
// Make them invulnerable
|
|
if ( HABD_GHOST_EFFECTS_ON == TRUE)
|
|
SetPlotFlag(oPC, TRUE);
|
|
else SetPlotFlag(oPC, FALSE);
|
|
|
|
// Make them ignored by hostiles
|
|
if (!GetLocalInt(oPC, HABD_OLD_FACTION_SET))
|
|
{
|
|
SetLocalInt(oPC, HABD_OLD_FACTION, GetStandardFactionReputation(STANDARD_FACTION_HOSTILE, oPC));
|
|
SetLocalInt(oPC, HABD_OLD_FACTION_SET, 1);
|
|
}
|
|
SetStandardFactionReputation(STANDARD_FACTION_HOSTILE, 100, oPC);
|
|
|
|
// Apply effects to make them a ghost.
|
|
// Don't set the concealment too high just incase they find a way to abuse the system.
|
|
effect eBad = EffectConcealment(1);
|
|
eBad = EffectLinkEffects(EffectVisualEffect(VFX_DUR_PROT_SHADOW_ARMOR), eBad);
|
|
eBad = EffectLinkEffects(EffectVisualEffect(VFX_DUR_GHOSTLY_VISAGE), eBad);
|
|
if ( HABD_GHOST_EFFECTS_ON == TRUE)
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBad, oPC, GHOST_LOOP_TIMER+2.0f);
|
|
//the ghost function reaplies the temporal effects (temporal to avoid logout
|
|
// bugs)
|
|
|
|
//Drop a corpse if needed, never when we apply respawn from persistence
|
|
//do it before the guy is moved from the area where the loot bag was placed!
|
|
if (HABD_DROP_CORPSE_ITEM == TRUE)
|
|
if (GetLocalInt(oPC, HABD_PERSISTANT_REAPPLY) != 1 )
|
|
{
|
|
object oLootBag = SearchDeathBag(oPC);
|
|
location lBag = GetLocation(oPC);
|
|
//if death bag is found, use location of death bag placeable
|
|
if (oLootBag!=OBJECT_INVALID)
|
|
lBag = GetLocation(oLootBag);
|
|
//we should create a corpse placeable if we dont
|
|
//found the placeable! Otherwise the corpse will be created at PC location
|
|
if (oLootBag==OBJECT_INVALID)
|
|
{
|
|
oLootBag = HABDCreateDeathBag(oPC);
|
|
if (oLootBag!=OBJECT_INVALID)
|
|
lBag = GetLocation(oLootBag);
|
|
}
|
|
object oICorpse = CreateCorpse(oPC, lBag, oLootBag);
|
|
}
|
|
|
|
//jump to waypoint when respawn.
|
|
//dont jump when coming from logout or persistence
|
|
if (GetLocalInt(oPC, HABD_PERSISTANT_REAPPLY) != 1 ||
|
|
GetLocalInt(oPC, HABD_FORCEJUMPTORESPAWNPOINT) == 1)
|
|
{
|
|
//Dinamic config feature
|
|
int irjold = -1;HABDRespawnTeleportNumber();
|
|
int irjnew = -1;HABDDinamicRespawnTeleport(Dinamic, irjold);
|
|
|
|
if (HABD_DINAMICRESPAWN1==0)
|
|
{
|
|
if (HABD_BINDSTONE_USEWHENRESPAWNED == TRUE )
|
|
HABDJumpToBindStonePoint (oPC);
|
|
else
|
|
JumpToRespawnPoint (oPC);
|
|
}
|
|
else
|
|
//Dinamic config feature
|
|
{
|
|
irjold = HABDRespawnTeleportNumber();
|
|
irjnew = HABDDinamicRespawnTeleport(Dinamic, irjold);
|
|
if (irjnew == 2)
|
|
HABDJumpToBindStonePoint (oPC);
|
|
else if (irjnew == 1)
|
|
JumpToRespawnPoint (oPC);
|
|
}
|
|
}
|
|
//See JumpToLocation Notes if you add code
|
|
if ( GetLocalInt(oPC, HABD_FORCEJUMPTORESPAWNPOINT) == 1 )
|
|
DeleteLocalInt(oPC, HABD_FORCEJUMPTORESPAWNPOINT);
|
|
|
|
|
|
if (GetLocalInt(oPC, HABD_PERSISTANT_REAPPLY) == TRUE)
|
|
DeleteLocalInt(oPC, HABD_PERSISTANT_REAPPLY);
|
|
|
|
if(HABD_USERLANGUAGE==0)
|
|
FloatingTextStringOnCreature("OOC: You now a spirit. Do not interact with the other players.", oPC, FALSE);
|
|
else if(HABD_USERLANGUAGE==1)
|
|
FloatingTextStringOnCreature("OOC: Eres un fantasma. Tu PJ no puede interactuar con otros jugadores.", oPC, FALSE);
|
|
|
|
//the delay is only needed to let the JumpToLocation work properly
|
|
if ( HABD_GHOST_COMMANDABLE == FALSE)
|
|
DelayCommand ( 0.001, SetCommandable(FALSE, oPC) );
|
|
|
|
//It will check if the PC is jumping to another area, when the PC finish his
|
|
//travel, a code for final instructions will be triggered. The function
|
|
//executed will be 'safe', we'll be sure that the PC is not travelling to another
|
|
//and the PC is not Commmandable
|
|
if ( USE_RespawnFinished_Function == TRUE )
|
|
DelayCommand ( 0.1, CheckGhostIsJumping(oPC) );
|
|
|
|
//We are mostly sure the PC is Respawned, but see below
|
|
|
|
//HardCore Respawn Feature, first check the function only if needed
|
|
//Dinamic Respawn Feature..
|
|
int iHardC = FALSE;
|
|
int idr = -1;
|
|
int AutoraiseHCOff = FALSE;
|
|
if (HABD_DINAMICRESPAWN1!=0)
|
|
{
|
|
idr = HABDDinamicRespawnAutoRaise(Dinamic);
|
|
if ( idr == 0 || idr ==1 )
|
|
if ( HABD_HARDCORE_RESPAWN1 == TRUE)
|
|
if ( HABDHardCoreRespawn(oPC)==TRUE )
|
|
iHardC = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( HABD_HARDCORE_RESPAWN1 == TRUE)
|
|
if ( HABDHardCoreRespawn(oPC)==TRUE )
|
|
iHardC = TRUE;
|
|
}
|
|
|
|
//Dinamic Respawn Feature, disallow Timer AutoRaise if needed.
|
|
//HardCore Respawn Feature, disallow Timer AutoRaise if needed
|
|
if (HABD_DINAMICRESPAWN1!=0)
|
|
{
|
|
if ( idr == 2)
|
|
{
|
|
if (GetIsPC(oPC) == TRUE && GetIsDMPossessed(oPC) == FALSE)
|
|
DeleteLocalInt(GetModule(), HABD_RAISE_TIMER+sID);
|
|
else
|
|
DeleteLocalInt(oPC, HABD_RAISE_TIMER);
|
|
AutoraiseHCOff = TRUE;
|
|
}
|
|
else
|
|
if ( (iHardC == TRUE) && (idr == 0 || idr ==1) )
|
|
{
|
|
if (GetIsPC(oPC) == TRUE && GetIsDMPossessed(oPC) == FALSE)
|
|
DeleteLocalInt(GetModule(), HABD_RAISE_TIMER+sID);
|
|
else
|
|
DeleteLocalInt(oPC, HABD_RAISE_TIMER);
|
|
AutoraiseHCOff = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if ( iHardC == TRUE)
|
|
{
|
|
if (GetIsPC(oPC) == TRUE && GetIsDMPossessed(oPC) == FALSE)
|
|
DeleteLocalInt(GetModule(), HABD_RAISE_TIMER+sID);
|
|
else
|
|
DeleteLocalInt(oPC, HABD_RAISE_TIMER);
|
|
AutoraiseHCOff = TRUE;
|
|
}
|
|
|
|
|
|
//HardCore feature message
|
|
if (AutoraiseHCOff == TRUE){
|
|
if(HABD_USERLANGUAGE==0)
|
|
FloatingTextStringOnCreature("OOC: AutoRaise disabled by HardCore rule. You can only be raised by other PCs or DMs.", oPC, FALSE);
|
|
else if(HABD_USERLANGUAGE==1)
|
|
FloatingTextStringOnCreature("OOC: AutoResurrecion desactivada por reglas HardCore. Tan solo podras ser resucitado por otro PJ o un DM.", oPC, FALSE);
|
|
|
|
}
|
|
|
|
//Instantly Raises Respawned PC
|
|
if (HABD_RESPAWN_IS_RAISE==TRUE)
|
|
{
|
|
if (HABD_DINAMICRESPAWN1==0)
|
|
if (iHardC = FALSE)
|
|
{
|
|
HABDForceAutoRaise(oPC);
|
|
return;
|
|
}
|
|
//Dinamic configs
|
|
else
|
|
if ( (iHardC == FALSE && idr <= 0 ) || idr == 3 )
|
|
HABDForceAutoRaise(oPC);
|
|
}
|
|
|
|
//We are 100% sure the PC is a ghost
|
|
|
|
// Handle the auto-raise timer ONLY when coming from logout or persistence
|
|
// otherwise AutoRaise & AutoRespawn are handled by OnPCDeath script..
|
|
// Note, it doesnt work with Henchmans, I dont know if it was needed because
|
|
// i cant test with henchmans.
|
|
float fRespawn = 0.0;
|
|
float fRaise = 0.0;
|
|
if (GetIsPC(oPC) == TRUE && GetIsDMPossessed(oPC) == FALSE)
|
|
{
|
|
fRespawn = IntToFloat(GetLocalInt(oMod, HABD_RESPAWN_TIMER+sID));
|
|
fRaise = IntToFloat(GetLocalInt(oMod, HABD_RAISE_TIMER+sID));
|
|
}
|
|
else
|
|
{
|
|
fRespawn = IntToFloat(GetLocalInt(oPC, HABD_RESPAWN_TIMER));
|
|
fRaise = IntToFloat(GetLocalInt(oPC, HABD_RAISE_TIMER));
|
|
}
|
|
// Autoraise timers will use their persistent values.
|
|
// Except if these values does not exist ;) because were deleted due to another autoraise
|
|
if (GetIsPC(oPC) == TRUE && GetIsDMPossessed(oPC) == FALSE)
|
|
{
|
|
if ( GetLocalInt(oMod, HABD_RESPAWN_TIMER+sID) <= 0 )
|
|
SetLocalInt(oMod, HABD_RESPAWN_TIMER+sID, FloatToInt(HABD_FORCE_RESPAWN_TIMER));
|
|
if(AutoraiseHCOff == FALSE)
|
|
{
|
|
if ( GetLocalInt(oMod, HABD_RAISE_TIMER+sID) <= 0 )
|
|
if ((HABD_SOLO_FORCE_RAISE_TIMER > 0.0) && (HABDPlayerIsSolo(oPC)==TRUE) )
|
|
{
|
|
SetLocalInt(oMod, HABD_RAISE_TIMER+sID, FloatToInt(HABD_SOLO_FORCE_RAISE_TIMER));
|
|
} else {
|
|
SetLocalInt(oMod, HABD_RAISE_TIMER+sID, FloatToInt(HABD_FORCE_RAISE_TIMER));
|
|
}
|
|
}
|
|
}
|
|
else //Henchmen
|
|
{
|
|
if ( GetLocalInt(oPC, HABD_RESPAWN_TIMER) <= 0 )
|
|
SetLocalInt(oPC, HABD_RESPAWN_TIMER, FloatToInt(HABD_NPC_FORCE_RESPAWN_TIMER));
|
|
if(AutoraiseHCOff == FALSE)
|
|
if ( GetLocalInt(oPC, HABD_RAISE_TIMER) <= 0 )
|
|
SetLocalInt(oPC, HABD_RAISE_TIMER, FloatToInt(HABD_NPC_FORCE_RAISE_TIMER));
|
|
}
|
|
//---
|
|
|
|
//Autoraise OnEnter
|
|
if (GetLocalInt(oPC, HABD_RESTORE_AUTO_RAISE) == 1 )
|
|
{
|
|
DeleteLocalInt(oPC, HABD_RESTORE_AUTO_RAISE);
|
|
int iMakeAutoRaise = TRUE;
|
|
if (fRaise > 0.0)
|
|
{
|
|
if (HABD_FORCE_RAISE_USES_SCROLLS)
|
|
{
|
|
if (HABDCheckForRaiseRezScrolls(oPC) <= 0)
|
|
{
|
|
if(HABD_USERLANGUAGE==0)
|
|
FloatingTextStringOnCreature("OOC: Out of scrolls. You have to wait for help.", oPC, FALSE);
|
|
else if(HABD_USERLANGUAGE==1)
|
|
FloatingTextStringOnCreature("OOC: Sin pergaminos. Debes esperar a que llegue ayuda.", oPC, FALSE);
|
|
|
|
iMakeAutoRaise = FALSE;
|
|
}
|
|
}
|
|
if (iMakeAutoRaise == TRUE)
|
|
{
|
|
//warn the player
|
|
if(fRaise > 1.0)
|
|
{
|
|
if(HABD_USERLANGUAGE==0)
|
|
FloatingTextStringOnCreature("OOC: "+GetName(oPC)+" will automatically raise in "+FloatToString(fRaise,4,1)+" seconds. AutoRaise for Respawned PC restored due to log-in, you wont receive further messages.", oPC, TRUE);
|
|
else if(HABD_USERLANGUAGE==1)
|
|
FloatingTextStringOnCreature("OOC: "+GetName(oPC)+" resucitara automaticamente en "+FloatToString(fRaise,4,1)+" segundos. AutoResurreccion para PJ Respawnado restaurada debido a que saliste y entraste del server, no recibiras mas mensajes.", oPC, TRUE);
|
|
|
|
}
|
|
//AutoRaise
|
|
//AssignCommand(oPC, DelayCommand(fRaise, HABDForceAutoRaise(oPC)));
|
|
AssignCommand(oPC, DelayCommand(IntToFloat(HABD_AUTOTIMERS_UPDATE), HABDAutoRaiseTimerUpdater(oPC, FloatToInt(fRaise))));
|
|
}
|
|
}
|
|
}
|
|
//End of Autoraise restoration OnEnter
|
|
|
|
//Save info to DB (and maybe export PC) to avoid server crash problems,
|
|
//now that we are sure the PC is Respawned.
|
|
if ( HABD_SMART_SAVETODB == TRUE )
|
|
HABDSetDBString(oPC);
|
|
}
|
|
|