Initial commit
Adding all of the current content for Anphillia Unlimited.
This commit is contained in:
910
_module/nss/chr_inc.nss
Normal file
910
_module/nss/chr_inc.nss
Normal file
@@ -0,0 +1,910 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// chr_inc
|
||||
// written by: eyesolated
|
||||
// written at: April 13, 2018
|
||||
//
|
||||
// Notes: Include File for Character related stuff
|
||||
|
||||
|
||||
///////////
|
||||
// Includes
|
||||
//
|
||||
#include "datetime_inc"
|
||||
#include "color_inc"
|
||||
#include "chr_cfg"
|
||||
#include "cnr_property_inc"
|
||||
#include "sql_inc"
|
||||
#include "util_inc"
|
||||
#include "util_names_inc"
|
||||
#include "nwnx_time"
|
||||
|
||||
//:: void main (){}
|
||||
|
||||
///////////////////////
|
||||
// Function Declaration
|
||||
//
|
||||
|
||||
// Rest functions
|
||||
|
||||
// Queues oObject as the Food object to use for next rest
|
||||
void chr_QueueFood(object oPC, object oObject);
|
||||
|
||||
// Starts the OnRest for oPC and nRestEvent
|
||||
void chr_OnRest(object oPC, int nRestEvent);
|
||||
|
||||
// Sets the AFK status on a player, including a nice effect
|
||||
void chr_SetAFKStatus(object oPC, int nIsAFK);
|
||||
|
||||
// Creates a player Backpack with Gold and items on the location of oPC
|
||||
void chr_Drop_Backpack(object oPC);
|
||||
|
||||
// Gets Ability name
|
||||
string chr_GetAbilityName(int nAbility, int nShort = FALSE);
|
||||
|
||||
// Gets Skill name
|
||||
string chr_GetSkillName(int nSkill);
|
||||
|
||||
// Does an ability check
|
||||
// DC: The DC to roll against, returns TRUE if Check succeded
|
||||
// nAbility: ABILITY_*
|
||||
// ShowMessage: Show a message to the player about the roll
|
||||
// ForceDelay: Don't do the roll if other rolls (Ability Checks, Saving Throws etc.) are currently active
|
||||
// ShowAnimation:Show an animation for rolling
|
||||
int chr_DoAbilityCheck(object oPC, int nAbility, int DC = 0, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE);
|
||||
|
||||
// Does an ability check
|
||||
// DC: The DC to roll against, returns TRUE if Check succeded
|
||||
// nAbility: ABILITY_*
|
||||
// ShowMessage: Show a message to the player about the roll
|
||||
// ForceDelay: Don't do the roll if other rolls (Ability Checks, Saving Throws etc.) are currently active
|
||||
// ShowAnimation:Show an animation for rolling
|
||||
// AllowUntrained: Allow rolling skills that would require training even if the character isn't trained in them
|
||||
int chr_DoSkillCheck(object oPC, int nSkill, int DC = 0, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE, int AllowUntrained = FALSE);
|
||||
|
||||
// Does a saving throw
|
||||
// DC: The DC to roll against, returns TRUE if Check succeded
|
||||
// nAbility: ABILITY_*
|
||||
// ShowMessage: Show a message to the player about the roll
|
||||
// ForceDelay: Don't do the roll if other rolls (Ability Checks, Saving Throws etc.) are currently active
|
||||
// ShowAnimation:Show an animation for rolling
|
||||
int chr_DoSavingThrow(object oPC, int nSaveType, int nDC = 0, int bShowMessage = FALSE, int bForceDelay = FALSE, int bShowAnimation = FALSE);
|
||||
|
||||
// Does a saving throw
|
||||
// DC: The DC to roll against, returns TRUE if Check succeded
|
||||
// nAbility: ABILITY_*
|
||||
// ShowMessage: Show a message to the player about the roll
|
||||
// ForceDelay: Don't do the roll if other rolls (Ability Checks, Saving Throws etc.) are currently active
|
||||
// ShowAnimation:Show an animation for rolling
|
||||
int chr_DoDieRoll(object oPC, int nSides, int nCount = 1, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE);
|
||||
|
||||
// This function should be called on ClientLeave, so the Character System can undo necessary things
|
||||
void chr_OnPlayerExit(object OPC);
|
||||
|
||||
// Returns the PC's persistence item that they will always have on them
|
||||
object chr_GetPCItem(object oPC);
|
||||
|
||||
// Returns the PC's unique integer ID, which is always >0
|
||||
// Returns <= 0 on error
|
||||
int chr_GetPCID(object oPC);
|
||||
|
||||
// Initializes the PC tracking system. Returns new PCID, or 0 if character already initialized
|
||||
int chr_InitializePC(object oPC);
|
||||
|
||||
// Returns the PC object corresponding to the given ID, if the PC is online at the time
|
||||
object chr_GetPCByPCID(int nPCID);
|
||||
|
||||
// Stores the message in the players last messages log
|
||||
void chr_LogPlayerChatMessage(object oPC, string sMessage);
|
||||
// Returns the nthLast message of the PC
|
||||
string chr_GetPlayerChatMessage(object oPC, int nthLast=0);
|
||||
// Sets whether the oPC's messages will be displayed as usual.
|
||||
void chr_SetPlayerCanSpeak(object oPC, int bCanSpeak=TRUE);
|
||||
// Gets whether the oPC's messages will be displayed as usual.
|
||||
int chr_GetPlayerCanSpeak(object oPC);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Internal Functions
|
||||
//
|
||||
|
||||
void DoRest(object oPC)
|
||||
{
|
||||
FadeToBlack(oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_SLEEP), oPC, 7.0f);
|
||||
DelayCommand(7.0f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_SLEEP), oPC, 7.0f));
|
||||
}
|
||||
|
||||
void SaveRestTime(object oPC)
|
||||
{
|
||||
SetLocalInt(oPC, CHR_REST_VAR_REST_TIME, NWNX_Time_GetTimeStamp());
|
||||
}
|
||||
|
||||
string GetNearbyHealer(object oPC)
|
||||
{
|
||||
object oHealer = GetNearestObjectByTag ("KaliaCain", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
oHealer = GetNearestObjectByTag ("ElrielDesifer", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
oHealer = GetNearestObjectByTag ("KadCulling", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
oHealer = GetNearestObjectByTag ("ClaraFenson", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
oHealer = GetNearestObjectByTag ("WanreDLloth", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
oHealer = GetNearestObjectByTag ("Wacoel", oPC);
|
||||
if (GetIsObjectValid(oHealer) && !GetIsDead(oHealer))
|
||||
return GetName(oHealer);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int GetIsPCInFreeRestArea(object oPC)
|
||||
{
|
||||
object oArea = GetArea(oPC);
|
||||
if (GetLocalInt(oArea, "FreeRest") == 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
object GetPCRestFood(object oPC)
|
||||
{
|
||||
object oMyFood;
|
||||
|
||||
// Is there any queued food available?
|
||||
oMyFood = GetLocalObject(oPC, CHR_REST_VAR_FOOD_QUEUE);
|
||||
if (GetIsObjectValid(oMyFood) &&
|
||||
GetItemPossessor(oMyFood) == oPC)
|
||||
{
|
||||
return oMyFood;
|
||||
}
|
||||
|
||||
// If not, cycle through the available food items
|
||||
object oEquip = GetFirstItemInInventory(oPC);
|
||||
while(GetIsObjectValid(oEquip)) {
|
||||
if(!FindSubString(CnrGetHcrCompatibleTag(GetTag(oEquip)),"Food")) {
|
||||
oMyFood = oEquip;
|
||||
break;
|
||||
}
|
||||
oEquip = GetNextItemInInventory(oPC);
|
||||
}
|
||||
return oMyFood;
|
||||
}
|
||||
|
||||
void doMonsterSurprise(object oPlayer)
|
||||
{
|
||||
// Possibly spawn monsters to a lonely resting player
|
||||
int nChanceToJump = d100(1);
|
||||
if (nChanceToJump <= CHR_REST_SURPRISE_CHANCE)
|
||||
return;
|
||||
|
||||
int nCreaturesToJump = Random(CHR_REST_SURPRISE_MONSTERS_MAX) + 1;
|
||||
|
||||
if (nCreaturesToJump > 0)
|
||||
{
|
||||
int nCreatureCount = 0;
|
||||
int nCreatureNumber = 1;
|
||||
object oNearestPCToCreature;
|
||||
float fDistanceToPC;
|
||||
object oCreatureSelected = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, oPlayer, nCreatureNumber, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
|
||||
while (GetIsObjectValid(oCreatureSelected) &&
|
||||
nCreatureCount < nCreaturesToJump)
|
||||
{
|
||||
oNearestPCToCreature = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oCreatureSelected);
|
||||
fDistanceToPC = GetDistanceBetween(oCreatureSelected, oNearestPCToCreature);
|
||||
if (fDistanceToPC > 35.0f)
|
||||
{
|
||||
DelayCommand(1.0f, AssignCommand(oCreatureSelected, ActionJumpToObject(oPlayer)));
|
||||
nCreatureCount++;
|
||||
}
|
||||
nCreatureNumber++;
|
||||
oCreatureSelected = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, oPlayer, nCreatureNumber, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int isGuarded(object oPC, int nRequiredGuards = 1)
|
||||
{
|
||||
int nth = 1;
|
||||
int nFoundGuards = 0;
|
||||
string sGuards = "";
|
||||
object oOtherPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oPC, nth);
|
||||
float fDistance;
|
||||
while (GetIsObjectValid(oOtherPC))
|
||||
{
|
||||
if (!GetIsResting(oOtherPC) &&
|
||||
!GetIsDM(oOtherPC))
|
||||
{
|
||||
fDistance = GetDistanceBetween(oPC, oOtherPC);
|
||||
if (fDistance > 35.0f)
|
||||
break;
|
||||
|
||||
nFoundGuards++;
|
||||
sGuards += " [" + color_ConvertString(GetName(oOtherPC), COLOR_GREEN) + "]";
|
||||
}
|
||||
nth++;
|
||||
oOtherPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oPC, nth);
|
||||
}
|
||||
if (nRequiredGuards <= nFoundGuards)
|
||||
{
|
||||
if (nFoundGuards > 4)
|
||||
sGuards = " " + IntToString(nFoundGuards) + " people.";
|
||||
SendMessageToPC(oPC, "You are guarded by:" + sGuards);
|
||||
//SendMessageToAllDMs(GetName(oPC) + " is resting in " + GetName(GetArea(oPC)) + " and is guarded by:" + sGuards);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageToPC(oPC, "You are resting alone.");
|
||||
SendMessageToAllDMs(COLOR_CODE_BLUE_DARK + GetName(oPC) + " is resting alone in " + GetName(GetArea(oPC)) + "." + COLOR_CODE_END);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void CancelRest(object oPC)
|
||||
{
|
||||
SetLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT, 1);
|
||||
}
|
||||
|
||||
int AllowRestByTime(object oPC)
|
||||
{
|
||||
// Get the current date/time
|
||||
int tNow = NWNX_Time_GetTimeStamp();
|
||||
// Get the last time the PC rested
|
||||
int tLastRest = GetLocalInt(oPC, CHR_REST_VAR_REST_TIME);
|
||||
|
||||
int tDifference = tNow - tLastRest;
|
||||
|
||||
if (tDifference < FloatToInt(HoursToSeconds(CHR_REST_INTERVAL_HOURS)))
|
||||
{
|
||||
float fHoursToWait = (HoursToSeconds(CHR_REST_INTERVAL_HOURS) - tDifference) / HoursToSeconds(1);
|
||||
SendMessageToPC(oPC, "You can't rest at this time, try again in " + FloatToString(fHoursToWait, 2, 1) + " hours.");
|
||||
CancelRest(oPC);
|
||||
AssignCommand(oPC, ClearAllActions());
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
void SendFamiliarAway(object oPC)
|
||||
{
|
||||
object oFamiliar = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
|
||||
if(!GetIsObjectValid(oFamiliar))
|
||||
oFamiliar= GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
|
||||
DestroyObject(oFamiliar);
|
||||
}
|
||||
|
||||
void RemoveBlackScreen(object oPC)
|
||||
{
|
||||
FadeFromBlack(oPC);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Function Code
|
||||
//
|
||||
|
||||
void chr_ZombieWalk(object oPC, int nDuration)
|
||||
{
|
||||
object oPCSkin = GetItemInSlot (INVENTORY_SLOT_CARMOUR, oPC);
|
||||
// We only relate this message once, it's just so they know what is going on.
|
||||
if (!GetLocalInt (oPC, CHR_NEARDEATH_VAR_MESSAGE))
|
||||
{
|
||||
FloatingTextStringOnCreature (CHR_NEARDEATH_MESSAGE, oPC, FALSE);
|
||||
SetLocalInt (oPC, CHR_NEARDEATH_VAR_MESSAGE, 1);
|
||||
}
|
||||
|
||||
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertySpecialWalk(0), oPCSkin, IntToFloat (nDuration));
|
||||
}
|
||||
|
||||
void ApplyFoodEffect(object oPC)
|
||||
{
|
||||
string sFoodTag = GetLocalString(oPC, CHR_REST_VAR_FOOD_TAG);
|
||||
effect eEffect;
|
||||
if (sFoodTag == "cnrRyeBread")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_STRENGTH, 1);
|
||||
else if (sFoodTag == "cnrWheatBread")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_DEXTERITY, 1);
|
||||
else if (sFoodTag == "cnrRiceBread")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_CONSTITUTION, 1);
|
||||
else if (sFoodTag == "cnrOatsBread")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_INTELLIGENCE, 1);
|
||||
else if (sFoodTag == "cnrCornBread")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_WISDOM, 1);
|
||||
else if (sFoodTag == "cnrApplePie")
|
||||
eEffect = EffectSavingThrowIncrease(SAVING_THROW_FORT, 1, SAVING_THROW_TYPE_POISON);
|
||||
else if (sFoodTag == "cnrCherryPie")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_CHARISMA, 1);
|
||||
else if (sFoodTag == "cnrBlkberryPie")
|
||||
eEffect = EffectSavingThrowIncrease(SAVING_THROW_FORT, 1, SAVING_THROW_TYPE_DISEASE);
|
||||
else if (sFoodTag == "cnrBluberryPie")
|
||||
eEffect = EffectAttackIncrease(1);
|
||||
else if (sFoodTag == "cnrPecanPie")
|
||||
eEffect = EffectAbilityIncrease(ABILITY_INTELLIGENCE, 1);
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, TurnsToSeconds(6));
|
||||
}
|
||||
|
||||
void chr_QueueFood(object oPC, object oObject)
|
||||
{
|
||||
if(!FindSubString(CnrGetHcrCompatibleTag(GetTag(oObject)),"Food"))
|
||||
{
|
||||
SetLocalObject(oPC, CHR_REST_VAR_FOOD_QUEUE, oObject);
|
||||
SendMessageToPC(oPC, "You will eat [" + color_ConvertString(GetName(oObject), COLOR_GREY) + "] on your next rest.");
|
||||
}
|
||||
}
|
||||
|
||||
void chr_OnRest(object oPC, int nRestEvent)
|
||||
{
|
||||
string sHealer;
|
||||
object oFood;
|
||||
string sFoodTag;
|
||||
switch (nRestEvent)
|
||||
{
|
||||
case REST_EVENTTYPE_REST_STARTED:
|
||||
{ SetLocalInt(oPC, CHR_REST_VAR_HITPOINTS_BEFORE_REST, GetCurrentHitPoints(oPC));
|
||||
sHealer = GetNearbyHealer(oPC);
|
||||
if (GetIsPCInFreeRestArea(oPC))
|
||||
{
|
||||
SetLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER, 1);
|
||||
}
|
||||
else if (sHealer != "")
|
||||
{
|
||||
SetLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER, 1);
|
||||
SendMessageToPC(oPC, sHealer + "'s presence is soothing you.");
|
||||
}
|
||||
else if (AllowRestByTime(oPC))
|
||||
{
|
||||
oFood = GetPCRestFood(oPC);
|
||||
if (!GetIsObjectValid(oFood))
|
||||
{
|
||||
FloatingTextStringOnCreature("You try to rest but you are too hungry.", oPC, FALSE);
|
||||
CancelRest(oPC);
|
||||
AssignCommand(oPC, ClearAllActions());
|
||||
return;
|
||||
}
|
||||
SendFamiliarAway(oPC);
|
||||
SetLocalString(oPC, CHR_REST_VAR_FOOD_TAG, GetTag(oFood));
|
||||
DestroyObject(oFood);
|
||||
DeleteLocalObject(oPC, CHR_REST_VAR_FOOD_QUEUE);
|
||||
SendMessageToPC(oPC, "You eat [" + color_ConvertString(GetName(oFood), COLOR_GREY) + "]");
|
||||
DoRest(oPC);
|
||||
if (!isGuarded(oPC, CHR_REST_SURPRISE_GUARDS_NEEDED))
|
||||
doMonsterSurprise(oPC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REST_EVENTTYPE_REST_CANCELLED:
|
||||
{
|
||||
if (GetLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER) == 1)
|
||||
{
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER);
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete the info on what food the PC ate
|
||||
DeleteLocalString(oPC, CHR_REST_VAR_FOOD_TAG);
|
||||
|
||||
if (GetLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT) == 1)
|
||||
{
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT);
|
||||
return;
|
||||
}
|
||||
// 120 seconds delay.
|
||||
SetLocalInt(oPC, CHR_REST_VAR_REST_TIME, GetLocalInt(oPC, CHR_REST_VAR_REST_TIME) + 120);
|
||||
|
||||
NWNX_Object_SetCurrentHitPoints(oPC, GetLocalInt(oPC, CHR_REST_VAR_HITPOINTS_BEFORE_REST));
|
||||
RemoveBlackScreen(oPC);
|
||||
break;
|
||||
}
|
||||
case REST_EVENTTYPE_REST_FINISHED:
|
||||
{ // Apply banked XP
|
||||
SendMessageToPC(oPC, "Apply XP");
|
||||
DelayCommand(0.0f, ExecuteScript("xp_apply", oPC));
|
||||
SendMessageToPC(oPC, "Fire PRC reset script");
|
||||
DelayCommand(0.0f, ExecuteScript("prc_rest", oPC));
|
||||
|
||||
SetLocalInt(oPC, CHR_REST_VAR_REST_TIME, NWNX_Time_GetTimeStamp());
|
||||
|
||||
if (GetLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER) == 1)
|
||||
{
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_NEARBYHEALER);
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT);
|
||||
return;
|
||||
}
|
||||
|
||||
NWNX_Object_SetCurrentHitPoints(oPC,
|
||||
min(GetMaxHitPoints(oPC), GetLocalInt(oPC, CHR_REST_VAR_HITPOINTS_BEFORE_REST) + 5 + GetHitDice(oPC)));
|
||||
|
||||
RemoveBlackScreen(oPC);
|
||||
DeleteLocalInt(oPC, CHR_REST_VAR_REST_CANCELLED_BY_SCRIPT);
|
||||
|
||||
// Apply Food effect and delete the info on what food the PC ate
|
||||
ApplyFoodEffect(oPC);
|
||||
DeleteLocalString(oPC, CHR_REST_VAR_FOOD_TAG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chr_SetAFKStatus(object oPC, int nIsAFK)
|
||||
{
|
||||
if (nIsAFK)
|
||||
{
|
||||
effect eImmobilize = EffectCutsceneImmobilize();
|
||||
eImmobilize = TagEffect(eImmobilize, CHR_AFK_EFFECTTAG);
|
||||
|
||||
vector vVector = GetPosition(oPC);
|
||||
int nCreatureSize = GetCreatureSize(oPC);
|
||||
switch (nCreatureSize)
|
||||
{
|
||||
case CREATURE_SIZE_SMALL: vVector.z += 0.7f; break;
|
||||
case CREATURE_SIZE_MEDIUM: vVector.z += 1.0f; break;
|
||||
case CREATURE_SIZE_LARGE: vVector.z += 1.3f; break;
|
||||
}
|
||||
location lLocation = Location(GetArea(oPC), vVector, GetFacing(oPC));
|
||||
|
||||
object oButterFlies = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_butterflies", lLocation);
|
||||
AssignCommand(oButterFlies, SetIsDestroyable(FALSE, FALSE, FALSE));
|
||||
SetLocalObject(oPC, CHR_AFK_VAR_PLACEABLE, oButterFlies);
|
||||
SetLocalInt(oPC, CHR_AFK_VAR_STATUS, TRUE);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImmobilize, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
object oButterFlies = GetLocalObject(oPC, CHR_AFK_VAR_PLACEABLE);
|
||||
if (GetIsObjectValid(oButterFlies))
|
||||
{
|
||||
AssignCommand(oButterFlies, SetIsDestroyable(TRUE, FALSE, FALSE));
|
||||
DestroyObject(oButterFlies, 0.1f);
|
||||
}
|
||||
DeleteLocalObject(oPC, CHR_AFK_VAR_PLACEABLE);
|
||||
DeleteLocalInt(oPC, CHR_AFK_VAR_STATUS);
|
||||
|
||||
effect eEffect = GetFirstEffect(oPC);
|
||||
while (GetIsEffectValid(eEffect))
|
||||
{
|
||||
if (GetEffectTag(eEffect) == CHR_AFK_EFFECTTAG)
|
||||
{
|
||||
RemoveEffect(oPC, eEffect);
|
||||
break;
|
||||
}
|
||||
eEffect = GetNextEffect(oPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chr_MoveInventoryToBackpack(object oOwner, object oDest, string sDropTags="")
|
||||
{
|
||||
if (!GetIsObjectValid(oDest))
|
||||
return;
|
||||
|
||||
object oItem = GetFirstItemInInventory(oOwner);
|
||||
while(oItem != OBJECT_INVALID)
|
||||
{
|
||||
if (GetItemCursedFlag(oItem))
|
||||
{
|
||||
oItem = GetNextItemInInventory(oOwner);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetHasInventory(oItem))
|
||||
{
|
||||
chr_MoveInventoryToBackpack(oItem, oDest, sDropTags);
|
||||
}
|
||||
|
||||
if (sDropTags == "" || FindSubString(sDropTags, GetTag(oItem)) >= 0)
|
||||
{
|
||||
CopyItem(oItem, oDest, TRUE);
|
||||
DestroyObject(oItem);
|
||||
}
|
||||
|
||||
oItem = GetNextItemInInventory (oOwner);
|
||||
}
|
||||
}
|
||||
|
||||
void chr_Drop_Backpack(object oPC)
|
||||
{
|
||||
location lDiedHere = GetLocation(oPC);
|
||||
object oMod = GetModule();
|
||||
object oBackpack;
|
||||
string sID=GetName(oPC)+GetPCPublicCDKey(oPC);
|
||||
|
||||
// Create a Backpack if there is none yet at this location
|
||||
oBackpack=GetLocalObject(oMod, "PlayerBackpack"+sID);
|
||||
if (!GetIsObjectValid(oBackpack) ||
|
||||
GetLocation(oBackpack) != lDiedHere)
|
||||
{
|
||||
oBackpack = CreateObject (OBJECT_TYPE_PLACEABLE, "playerbackpack", lDiedHere);
|
||||
|
||||
if (!GetIsObjectValid (oBackpack))
|
||||
SendMessageToPC (oPC, "invalid backpack");
|
||||
|
||||
SetLocalObject(oMod,"PlayerBackpack"+sID, oBackpack);
|
||||
}
|
||||
|
||||
// Drop player gold
|
||||
int nAmtGold=GetGold(oPC);
|
||||
WriteTimestampedLogEntry ("Dropping gold from player - " + IntToString (nAmtGold));
|
||||
AssignCommand(oPC, TakeGoldFromCreature(nAmtGold, oPC, TRUE));
|
||||
if (nAmtGold > CHR_DROP_GOLDMAXIMUM)
|
||||
nAmtGold = CHR_DROP_GOLDMAXIMUM;
|
||||
if (nAmtGold > 0)
|
||||
CreateItemOnObject("NW_IT_GOLD001", oBackpack, nAmtGold);
|
||||
|
||||
// Drop Items
|
||||
if (CHR_DROP_ITEMS)
|
||||
{
|
||||
string sDropTags = "playercorpse;";
|
||||
sDropTags += "cnrNuggetCopp;cnrNuggetTin;cnrNuggetIron;cnrNuggetGold;cnrNuggetPlat;cnrNuggetAdam;cnrNuggetCoba;cnrNuggetSilv;cnrNuggetTita;cnrNuggetMith;";
|
||||
sDropTags += "cnrGemMineral001;cnrGemMineral007;cnrGemMineral002;cnrGemMineral014;cnrGemMineral004;cnrGemMineral003;cnrGemMineral015;cnrGemMineral011;cnrGemMineral013;cnrGemMineral010;cnrGemMineral008;cnrGemMineral009;cnrGemMineral005;cnrGemMineral006;cnrGemMineral012;";
|
||||
sDropTags += "cnrBranchHic;cnrBranchOak;cnrBranchMah;";
|
||||
sDropTags += "ANPH_SUPPLIES_GOLD;ANPH_SUPPLIES_MAGIC;ANPH_SUPPLIES_ARMS;ANPH_SUPPLIES_ARMOR;";
|
||||
|
||||
chr_MoveInventoryToBackpack(oPC, oBackpack, sDropTags);
|
||||
}
|
||||
|
||||
// If the Backpack is empty, destroy it
|
||||
object oItem = GetFirstItemInInventory (oBackpack);
|
||||
if (!GetIsObjectValid (oItem))
|
||||
DestroyObject (oBackpack);
|
||||
}
|
||||
|
||||
string chr_GetAbilityName(int nAbility, int nShort = FALSE)
|
||||
{
|
||||
switch (nAbility)
|
||||
{
|
||||
case ABILITY_STRENGTH:
|
||||
if (nShort)
|
||||
return "STR";
|
||||
else
|
||||
return "Strength";
|
||||
break;
|
||||
case ABILITY_DEXTERITY:
|
||||
if (nShort)
|
||||
return "DEX";
|
||||
else
|
||||
return "Dexterity";
|
||||
break;
|
||||
case ABILITY_CONSTITUTION:
|
||||
if (nShort)
|
||||
return "CON";
|
||||
else
|
||||
return "Constitution";
|
||||
break;
|
||||
case ABILITY_WISDOM:
|
||||
if (nShort)
|
||||
return "WIS";
|
||||
else
|
||||
return "Wisdom";
|
||||
break;
|
||||
case ABILITY_INTELLIGENCE:
|
||||
if (nShort)
|
||||
return "INT";
|
||||
else
|
||||
return "Intelligence";
|
||||
break;
|
||||
case ABILITY_CHARISMA:
|
||||
if (nShort)
|
||||
return "CHA";
|
||||
else
|
||||
return "Charisma";
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string chr_GetSkillName(int nSkill)
|
||||
{
|
||||
return GetStringByStrRef(StringToInt(Get2DAString("skills", "Name", nSkill)));
|
||||
}
|
||||
|
||||
int chr_GetCurrentlyChecking(object oPC, int ShowMessage)
|
||||
{
|
||||
if (GetLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING))
|
||||
{
|
||||
if (ShowMessage)
|
||||
SendMessageToPC(oPC, "You recently did a Roll, please don't spam.");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void chr_DoMessage(object oPC, string sMessage)
|
||||
{
|
||||
SendMessageToPC(oPC, sMessage);
|
||||
|
||||
// Always send Message to DMs regardless of privacy status
|
||||
SendMessageToAllDMs(color_ConvertString(GetName(oPC), COLOR_GREY) + " - " + sMessage);
|
||||
float fDistance = 30.0f;
|
||||
|
||||
int nPrivacy = GetLocalInt(oPC, CS_ROLLS_VAR_PRIVACY);
|
||||
if (nPrivacy == CHR_ROLL_PRIVACY_PUBLIC)
|
||||
{
|
||||
location lLocation = GetLocation(oPC);
|
||||
object oByStander = GetFirstObjectInShape(SHAPE_SPHERE, fDistance, lLocation, TRUE, OBJECT_TYPE_CREATURE);
|
||||
while (GetIsObjectValid(oByStander))
|
||||
{
|
||||
if (GetIsPC(oByStander) &&
|
||||
!GetIsDM(oByStander) &&
|
||||
oPC != oByStander)
|
||||
{
|
||||
SendMessageToPC(oByStander, color_ConvertString(GetName(oPC), COLOR_GREY) + " - " + sMessage);
|
||||
}
|
||||
|
||||
oByStander = GetNextObjectInShape(SHAPE_SPHERE, fDistance, lLocation, TRUE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chr_DoCheckAnimationAndMessage(object oPC, int ShowMessage, int ShowAnimation, string sMessage, int nAnimation = ANIMATION_LOOPING_GET_MID, float fDuration = 2.0f)
|
||||
{
|
||||
// Roll Animation
|
||||
if (ShowAnimation)
|
||||
{
|
||||
AssignCommand(oPC, ClearAllActions());
|
||||
AssignCommand(oPC, ActionPlayAnimation(nAnimation, 1.0f, fDuration));
|
||||
}
|
||||
|
||||
if (ShowMessage)
|
||||
AssignCommand(GetModule(), DelayCommand(2.1f, chr_DoMessage(oPC, sMessage)));
|
||||
}
|
||||
|
||||
void chr_DeleteCheck(object oPC)
|
||||
{
|
||||
DeleteLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING);
|
||||
}
|
||||
|
||||
int chr_DoAbilityCheck(object oPC, int nAbility, int nDC = 0, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE)
|
||||
{
|
||||
if (ForceDelay)
|
||||
{
|
||||
if (chr_GetCurrentlyChecking(oPC, ShowMessage))
|
||||
return FALSE;
|
||||
|
||||
SetLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING, TRUE);
|
||||
// Reset Check in Progress
|
||||
AssignCommand(GetModule(), DelayCommand(3.0f, chr_DeleteCheck(oPC)));
|
||||
}
|
||||
|
||||
int nAbilityModifier = GetAbilityModifier(nAbility, oPC);
|
||||
int nRoll = d20();
|
||||
int nResult = nAbilityModifier + nRoll;
|
||||
|
||||
// Build Message
|
||||
string sMessage = "[" + color_ConvertString(chr_GetAbilityName(nAbility, TRUE), COLOR_ORANGE) + "] Check: ";
|
||||
sMessage += color_ConvertString(IntToString(nResult), COLOR_GREY);
|
||||
if (nDC != 0)
|
||||
sMessage += " (DC: " + color_ConvertString(IntToString(nDC), COLOR_GREY) + ")";
|
||||
|
||||
chr_DoCheckAnimationAndMessage(oPC, ShowMessage, ShowAnimation, sMessage);
|
||||
|
||||
if (nDC != 0)
|
||||
return (nDC <= nResult);
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
int chr_DoSkillCheck(object oPC, int nSkill, int nDC = 0, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE, int AllowUntrained = FALSE)
|
||||
{
|
||||
if (ForceDelay)
|
||||
{
|
||||
if (chr_GetCurrentlyChecking(oPC, ShowMessage))
|
||||
return FALSE;
|
||||
|
||||
SetLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING, TRUE);
|
||||
// Reset Check in Progress
|
||||
AssignCommand(GetModule(), DelayCommand(3.0f, chr_DeleteCheck(oPC)));
|
||||
}
|
||||
|
||||
int nBaseScore = GetSkillRank(nSkill, oPC, TRUE);
|
||||
if (nBaseScore == -1 &&
|
||||
!AllowUntrained)
|
||||
{
|
||||
if (ShowMessage)
|
||||
SendMessageToPC(oPC, "You don't have that skill.");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
int nSkillScore = GetSkillRank(nSkill, oPC);
|
||||
|
||||
int nRoll = d20();
|
||||
int nResult = nSkillScore + nRoll;
|
||||
|
||||
// Build Message
|
||||
string sMessage = "[" + color_ConvertString(chr_GetSkillName(nSkill), COLOR_ORANGE) + "] Check: ";
|
||||
sMessage += color_ConvertString(IntToString(nResult), COLOR_GREY);
|
||||
if (nDC != 0)
|
||||
sMessage += " (DC: " + color_ConvertString(IntToString(nDC), COLOR_GREY) + ")";
|
||||
|
||||
chr_DoCheckAnimationAndMessage(oPC, ShowMessage, ShowAnimation, sMessage);
|
||||
|
||||
if (nDC != 0)
|
||||
return (nDC <= nResult);
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
int chr_DoSavingThrow(object oPC, int nSaveType, int nDC = 0, int bShowMessage = FALSE, int bForceDelay = FALSE, int bShowAnimation = FALSE)
|
||||
{
|
||||
if (bForceDelay)
|
||||
{
|
||||
if (chr_GetCurrentlyChecking(oPC, bShowMessage))
|
||||
return FALSE;
|
||||
|
||||
SetLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING, TRUE);
|
||||
// Reset Check in Progress
|
||||
AssignCommand(GetModule(), DelayCommand(3.0f, chr_DeleteCheck(oPC)));
|
||||
}
|
||||
|
||||
int nSavingThrow;
|
||||
string sSaveType;
|
||||
switch (nSaveType)
|
||||
{
|
||||
case SAVING_THROW_FORT: nSavingThrow = GetFortitudeSavingThrow(oPC); sSaveType = "Fortitude"; break;
|
||||
case SAVING_THROW_REFLEX: nSavingThrow = GetReflexSavingThrow(oPC); sSaveType = "Reflex"; break;
|
||||
case SAVING_THROW_WILL: nSavingThrow = GetWillSavingThrow(oPC); sSaveType = "Will"; break;
|
||||
}
|
||||
int nRoll = d20();
|
||||
int nResult = nSavingThrow + nRoll;
|
||||
|
||||
// Build Message
|
||||
string sMessage = "[" + color_ConvertString(sSaveType, COLOR_ORANGE) + "] Saving Throw: ";
|
||||
sMessage += color_ConvertString(IntToString(nResult), COLOR_GREY);
|
||||
if (nDC != 0)
|
||||
sMessage += " (DC: " + color_ConvertString(IntToString(nDC), COLOR_GREY) + ")";
|
||||
|
||||
chr_DoCheckAnimationAndMessage(oPC, bShowMessage, bShowAnimation, sMessage);
|
||||
|
||||
if (nDC != 0)
|
||||
return (nDC <= nResult);
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
int chr_DoDieRoll(object oPC, int nSides, int nCount = 1, int ShowMessage = FALSE, int ForceDelay = FALSE, int ShowAnimation = FALSE)
|
||||
{
|
||||
if (ForceDelay)
|
||||
{
|
||||
if (chr_GetCurrentlyChecking(oPC, ShowMessage))
|
||||
return FALSE;
|
||||
|
||||
SetLocalInt(oPC, CHR_ROLL_VAR_CURRENTLYCHECKING, TRUE);
|
||||
// Reset Check in Progress
|
||||
AssignCommand(GetModule(), DelayCommand(3.0f, chr_DeleteCheck(oPC)));
|
||||
}
|
||||
|
||||
int nth;
|
||||
int nRoll;
|
||||
int nResult = 0;
|
||||
for (nth = 1; nth <= nCount; nth++)
|
||||
{
|
||||
nRoll = Random(nSides) + 1;
|
||||
nResult += nRoll;
|
||||
}
|
||||
|
||||
// Build Message
|
||||
string sMessage = "[" + IntToString(nCount) + "d" + color_ConvertString(IntToString(nSides), COLOR_ORANGE) + "]: ";
|
||||
sMessage += color_ConvertString(IntToString(nResult), COLOR_GREY);
|
||||
|
||||
chr_DoCheckAnimationAndMessage(oPC, ShowMessage, ShowAnimation, sMessage);
|
||||
|
||||
return nResult;
|
||||
}
|
||||
|
||||
void chr_OnPlayerExit(object oPC)
|
||||
{
|
||||
chr_SetAFKStatus(oPC, FALSE);
|
||||
}
|
||||
|
||||
object chr_GetPCItem(object oPC)
|
||||
{
|
||||
object oPCItem = GetLocalObject(oPC, "chr_PCITEM");
|
||||
if (!GetIsObjectValid(oPCItem))
|
||||
{
|
||||
oPCItem = GetItemPossessedBy(oPC, CHR_PCITEM_TAG);
|
||||
if (oPCItem == OBJECT_INVALID)
|
||||
{
|
||||
oPCItem = CreateItemOnObject(CHR_PCITEM_RESREF, oPC);
|
||||
}
|
||||
SetLocalObject(oPC, "chr_PCITEM", oPCItem);
|
||||
}
|
||||
return oPCItem;
|
||||
}
|
||||
|
||||
int chr_GetPCID(object oPC)
|
||||
{
|
||||
if (!GetIsPC(oPC) || GetIsObjectValid(GetMaster(oPC)))
|
||||
return -1;
|
||||
|
||||
int nID = StringToInt(GetTag(oPC));
|
||||
if (!nID)
|
||||
{
|
||||
nID = GetLocalInt(chr_GetPCItem(oPC), "chr_PCID");
|
||||
if (!nID)
|
||||
nID = sql_GetPCID(oPC);
|
||||
SetTag(oPC, IntToString(nID));
|
||||
//SetLocalObject(GetModule(), "chr_PCID_" + IntToString(nID), oPC);
|
||||
}
|
||||
return nID;
|
||||
}
|
||||
|
||||
int chr_InitializePC(object oPC)
|
||||
{
|
||||
//if (!GetIsPC(oPC) || GetIsObjectValid(GetMaster(oPC)))
|
||||
// return 0;
|
||||
|
||||
object oPCItem = chr_GetPCItem(oPC);
|
||||
|
||||
// Sanity check, avoid double inits
|
||||
if (StringToInt(GetTag(oPC)) || GetLocalInt(oPCItem, "chr_PCID"))
|
||||
return 0;
|
||||
|
||||
int nPCID = sql_RegisterNewPC(oPC);
|
||||
if (!GetIsObjectValid(oPCItem))
|
||||
{
|
||||
oPCItem = CreateItemOnObject(CHR_PCITEM_RESREF, oPC, 1, CHR_PCITEM_TAG);
|
||||
SetItemCursedFlag(oPCItem, TRUE);
|
||||
SetStolenFlag(oPCItem, TRUE);
|
||||
}
|
||||
|
||||
SetTag(oPC, IntToString(nPCID));
|
||||
|
||||
SetLocalInt(oPC, "chr_PCID", nPCID);
|
||||
SetLocalObject(oPC, "chr_PCITEM", oPCItem);
|
||||
return nPCID;
|
||||
}
|
||||
|
||||
object chr_GetPCByPCID(int nPCID)
|
||||
{
|
||||
object oPC = GetLocalObject(GetModule(), "chr_PCID_" + IntToString(nPCID));
|
||||
if (oPC != OBJECT_INVALID) // may still not be valid, but caller will check
|
||||
return oPC;
|
||||
oPC = GetFirstPC();
|
||||
while (oPC != OBJECT_INVALID)
|
||||
{
|
||||
if (chr_GetPCID(oPC) > 0)
|
||||
return oPC;
|
||||
oPC = GetNextPC();
|
||||
}
|
||||
return oPC;
|
||||
}
|
||||
|
||||
|
||||
void chr_LogPlayerChatMessage(object oPC, string sMessage)
|
||||
{
|
||||
int nPos = GetLocalInt(oPC, "CHR_CHAT_MESSAGE_BUFFER_POS");
|
||||
SetLocalString(oPC, "CHR_CHAT_MESSAGE_BUFFER_" + IntToString(nPos), sMessage);
|
||||
nPos = (nPos + 1) % CHR_CHAT_MESSAGE_BUFFER_SIZE;
|
||||
SetLocalInt(oPC, "CHR_CHAT_MESSAGE_BUFFER_POS", nPos);
|
||||
}
|
||||
|
||||
string chr_GetPlayerChatMessage(object oPC, int nthLast=0)
|
||||
{
|
||||
if (nthLast >= CHR_CHAT_MESSAGE_BUFFER_SIZE)
|
||||
return "";
|
||||
|
||||
int nPos = GetLocalInt(oPC, "CHR_CHAT_MESSAGE_BUFFER_POS");
|
||||
nPos = (CHR_CHAT_MESSAGE_BUFFER_SIZE + nPos - nthLast - 1) % CHR_CHAT_MESSAGE_BUFFER_SIZE;
|
||||
return GetLocalString(oPC, "CHR_CHAT_MESSAGE_BUFFER_" + IntToString(nPos));
|
||||
}
|
||||
|
||||
void chr_SetPlayerCanSpeak(object oPC, int bCanSpeak=TRUE)
|
||||
{
|
||||
SetLocalInt(oPC, "CHR_CHAT_IS_MUTED", !bCanSpeak);
|
||||
}
|
||||
|
||||
int chr_GetPlayerCanSpeak(object oPC)
|
||||
{
|
||||
return !GetLocalInt(oPC, "CHR_CHAT_IS_MUTED");
|
||||
}
|
||||
Reference in New Issue
Block a user