Here's the onenter:
#include "hg_inc"
#include "hg_area_inc"
#include "hg_antiex_inc"
#include "fky_environ_inc"
#include "ac_qstatus_inc"
#include "tsk_inc"
void DoAreaEffects (object oArea, object oPC, int nDamAmount, int nDamType, int nDamVis, string sMessage) {
if (GetArea(oPC) != oArea)
return;
if (!GetIsDead(oPC) && !GetPlotFlag(oPC)) {
if (nDamType < 0) {
if (nDamType == -1) {
int nBreath = GetCanBreatheWater(oPC, TRUE);
if (nBreath == 2)
return;
if (!nBreath) {
if (GetLocalInt(oPC, "Area_WaterBreath_Warning") < 3) {
FloatingTextStringOnCreature("You cannot hold your breath much longer!", oPC, FALSE);
AddLocalInt(oPC, "Area_WaterBreath_Warning", 1);
} else {
FloatingTextStringOnCreature("You can no longer hold your breath!", oPC, FALSE);
DeleteLocalInt(oPC, "Area_WaterBreath_Warning");
ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDeath()), oPC);
}
} else
DeleteLocalInt(oPC, "Area_WaterBreath_Warning");
} else if (nDamType == -2) {
int nLev = GetCanLevitate(oPC);
if (nLev == 2)
return;
if (!nLev) {
if (!GetIsResting(oPC))
FloatingTextStringOnCreature("You are unable to control your motion in the air!", oPC, FALSE);
RemoveEffectsOfType(EFFECT_TYPE_CUTSCENEIMMOBILIZE, oPC, oArea);
effect eEff = SupernaturalEffect(EffectCutsceneImmobilize());
DelayCommand(0.01, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEff, oPC, 9.0));
}
} else if (nDamType == -3) {
/* passwall; do nothing */
return;
} else if (nDamType == -4) {
int nFirewalk = GetCanFirewalk(oPC);
if (nFirewalk == 2)
return;
if (!nFirewalk) {
FloatingTextStringOnCreature("You are unable to breathe elemental fire!", oPC, FALSE);
ApplyDirectDamage(oPC, (GetMaxHitPoints(oPC) * 2) / 5, DAMAGE_TYPE_INTERNAL,
DAMAGE_POWER_ENERGY, "Elemental Fire", "You burn to a crisp!");
ApplyVisualToObject(VFX_IMP_FLAME_M, oPC);
}
}
} else {
effect eDam = EffectDamage(d10(nDamAmount), nDamType);
effect eVis = EffectVisualEffect(nDamVis);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oPC);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
if (sMessage != "")
FloatingTextStringOnCreature(sMessage, oPC, FALSE);
}
}
DelayCommand(6.0, DoAreaEffects(oArea, oPC, nDamAmount, nDamType, nDamVis, sMessage));
}
void DoDust (object oPC, object oItem) {
SetPlotFlag(oItem, FALSE);
DestroyObject(oItem);
CreateItemOnObject("drowdust", oPC);
}
object GetVFXLoopTarget (object oSource, string sTarget) {
int nCount = 1;
struct SubString ss = GetFirstSubString(sTarget, "#");
if (ss.rest != "") {
}
return GetNearestObjectByTag(ss.first, oSource, nCount);
}
float GetVFXLoopVaryingFloat (float fRand) {
int nVary = FloatToInt(fRand * 100.0);
nVary = Random((nVary * 2) + 1) - nVary;
return (nVary * 0.01);
}
void VoidBroadcastProjectileToObject (object oSource, object oTarget, int nSpellId, int nDelay) {
BroadcastProjectileToObject(oSource, oTarget, nSpellId, nDelay);
}
void DoVFXLoop (object oVFX, int nVis, float fCyc, float fDur, string sTarget, int bBeam,
float fCycRand, float fDurRand, int nMulti, float fMultiInt, float fMultiRand) {
if (GetLocalInt(OBJECT_SELF, "Area_Clear")) {
AddLocalInt(OBJECT_SELF, "Area_VFX_Active", -1);
return;
}
if (nMulti > 1) {
/* ugly to have a second copy, but removes unnecessary delaycommands */
int i;
float fDelay = 0.0;
for (i = 0; i < nMulti; i++) {
float fDurVary = GetVFXLoopVaryingFloat(fDurRand);
if (sTarget != "") {
object oTarget = GetVFXLoopTarget(oVFX, sTarget);
if (bBeam) {
effect eBeam = EffectBeam(nVis, oVFX, BODY_NODE_CHEST, (bBeam == 2));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam, oTarget, fDur + fDurVary));
} else if (nVis < 0) {
DelayCommand(fDelay, VoidBroadcastProjectileToObject(oVFX, oTarget, -nVis, FloatToInt((fDur + fDurVary) * 1000.0)));
} else if (fDur > 0.0) {
effect eVis = EffectVisualEffect(nVis);
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, fDur + fDurVary));
} else {
DelayCommand(fDelay, ApplyVisualToObject(nVis, oTarget));
}
} else {
if (fDur > 0.0) {
effect eVis = EffectVisualEffect(nVis);
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oVFX, fDur + fDurVary));
} else {
DelayCommand(fDelay, ApplyVisualToObject(nVis, oVFX));
}
}
fDelay += fMultiInt + GetVFXLoopVaryingFloat(fMultiRand);
}
} else {
float fDurVary = GetVFXLoopVaryingFloat(fDurRand);
if (sTarget != "") {
object oTarget = GetVFXLoopTarget(oVFX, sTarget);
if (bBeam) {
effect eBeam = EffectBeam(nVis, oVFX, BODY_NODE_CHEST, (bBeam == 2));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam, oTarget, fDur + fDurVary);
} else if (nVis < 0) {
BroadcastProjectileToObject(oVFX, oTarget, -nVis, FloatToInt((fDur + fDurVary) * 1000.0));
} else if (fDur > 0.0) {
effect eVis = EffectVisualEffect(nVis);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, fDur + fDurVary);
} else {
ApplyVisualToObject(nVis, oTarget);
}
} else {
if (fDur > 0.0) {
effect eVis = EffectVisualEffect(nVis);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oVFX, fDur + fDurVary);
} else {
ApplyVisualToObject(nVis, oVFX);
}
}
}
float fCycVary = GetVFXLoopVaryingFloat(fCycRand);
DelayCommand(fCyc + fCycVary, DoVFXLoop(oVFX, nVis, fCyc, fDur, sTarget, bBeam, fCycRand, fDurRand, nMulti, fMultiInt, fMultiRand));
}
void main () {
object oPC = GetEnteringObject();
object oArea = GetArea(oPC);
if (GetIsPC(oPC)) {
DeleteLocalInt(oArea, "Area_Clear");
int bReveal = GetLocalInt(oArea, "Area_Reveal");
if (bReveal > 0)
ExploreAreaForPlayer(oArea, oPC, TRUE);
}
if (GetLocalString(oPC, "FKY_CHAT_PASSWORD_IP") == "CHECK")
AssignCommand(GenCreator(), ApplyPasswordHold(oPC));
/* execute specific onenter script if specified */
string sScript = GetLocalString(oArea, "Area_OnEnter");
if (sScript != "")
ExecuteScript(sScript, oArea);
/* PC-only stuff below here */
if (!GetIsPC(oPC))
return;
if (GetLocalInt(oArea, "Area_VFX_Objects") > 0 &&
GetLocalInt(oArea, "Area_VFX_Active") == 0) {
int i, nObjects = GetLocalInt(oArea, "Area_VFX_Objects");
object oVFX;
for (i = 0; i < nObjects; i++) {
oVFX = GetLocalObject(oArea, "Area_VFX_Object_" + IntToString(i));
if (GetIsObjectValid(oVFX)) {
int nVis = GetLocalInt(oVFX, "VFX_Loop");
int nMulti = GetLocalInt(oVFX, "VFX_Loop_Multi");
int bBeam = GetLocalInt(oVFX, "VFX_Loop_Beam");
float fCyc = GetLocalFloat(oVFX, "VFX_Loop_Cycle");
float fCycRand = GetLocalFloat(oVFX, "VFX_Loop_Cycle_Vary");
float fDur = GetLocalFloat(oVFX, "VFX_Loop_Dur");
float fDurRand = GetLocalFloat(oVFX, "VFX_Loop_Dur_Vary");
float fMultiInt = GetLocalFloat(oVFX, "VFX_Loop_Multi_Int");
float fMultiRand = GetLocalFloat(oVFX, "VFX_Loop_Multi_Int_Vary");
string sTarget = GetLocalString(oVFX, "VFX_Loop_Target");
AddLocalInt(oArea, "Area_VFX_Active", 1);
AssignCommand(oArea, DelayCommand(fCyc, DoVFXLoop(oVFX, nVis, fCyc, fDur, sTarget, bBeam, fCycRand, fDurRand, nMulti, fMultiInt, fMultiRand)));
}
}
}
/* if the PC is not allowed in the area, boot them and return */
if (!CheckAreaTagRequirement(oArea, oPC))
return;
string sQuest = GetLocalString(oArea, "Area_Quest");
if (sQuest != "")
QSAddQuestStatus(sQuest, 1);
/* for Hell and Limbo areas, set the Succor_ local */
if (GetLocalInt(oArea, "notele") > 0)
SetLocalInt(oPC, "Succor_" + GetResRef(oArea), 1);
/* area damage/underwater areas */
/* TODO: enhance this to be more generic, e.g. Hells penalties */
if (!GetIsDM(oPC)) {
int nDamType = GetLocalInt(oArea, "Area_Damage_Type");
if (GetLocalInt(oArea, "Area_Underwater"))
nDamType = -1;
else if (GetLocalInt(oArea, "Area_Aerial"))
nDamType = -2;
else if (GetLocalInt(oArea, "Area_Passwall"))
nDamType = -3;
else if (GetLocalInt(oArea, "Area_Firewalk"))
nDamType = -4;
if (nDamType) {
int nDamAmount = GetLocalInt(oArea, "Area_Damage_Amount");
int nDamVis = GetLocalInt(oArea, "Area_Damage_VFX");
string sMessage = GetLocalString(oArea, "Area_Damage_Message");
AssignCommand(oArea, DoAreaEffects(oArea, oPC, nDamAmount, nDamType, nDamVis, sMessage));
}
/* destroy items that cannot survive in daylight */
if (GetIsDay() &&
!GetIsAreaInterior(oArea) &&
GetIsAreaAboveGround(oArea)) {
int i;
object oItem;
for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
oItem = GetItemInSlot(i, oPC);
if (GetStringLeft(GetTag(oItem), 4) == "asdf")
DoDust(oPC, oItem);
}
if (GetIsObjectValid(oItem = GetItemPossessedBy(oPC, "sealofshadows")))
DestroyObject(oItem);
}
}
/* spawn anything specified in area locals */
int nSpawns = GetLocalInt(oArea, "Area_Spawns");
string sTask;
struct IntList li;
if (nSpawns > 0) {
int i, nType;
string sKey, sTag, sRes, sLoc, sLocType;
object oSpawn;
location lSpawn;
for (i = 1; i <= nSpawns; i++) {
sKey = "Area_Spawn_" + IntToString(i);
sTag = GetLocalString(oArea, sKey + "_Tag");
/* if the object has already been spawned, skip it */
if (sTag != "") {
if (GetIsObjectValid(GetNearestObjectByTag(sTag, oPC)))
continue;
} else {
if (GetIsObjectValid(GetLocalObject(oArea, sKey + "_Obj")))
continue;
}
sRes = GetLocalString(oArea, sKey + "_Res");
sLoc = GetLocalString(oArea, sKey + "_Loc");
nType = GetLocalInt(oArea, sKey + "_Type");
if (nType == 0)
nType = OBJECT_TYPE_CREATURE;
sLocType = GetStringLeft(sLoc, 1);
if (sLocType == "!")
lSpawn = GetLocation(GetNearestObjectByTag(GetSubString(sLoc, 1, 64), oPC));
else if (sLocType == "@")
lSpawn = GetLocation(GetWaypointByTag(GetSubString(sLoc, 1, 64)));
else if (sLocType == "&") {//designates task creature, only spawn if pc requires (uses waypoint) ex: tsk_cr_1_2
sTask = GetStringRight(sRes, (GetStringLength(sRes) - 7));
li = GetIntList(sTask, "_");
if (!GetPCHasTaskActive(oPC, li.i0) || (GetTaskCompleted(oPC, li.i0) != (li.i1 - 1)))//if they don't have the task active, don't spawn
continue;
else
lSpawn = GetLocation(GetWaypointByTag(GetSubString(sLoc, 1, 64)));
} else
continue;
if (GetAreaFromLocation(lSpawn) == oArea) {
oSpawn = CreateObject(nType, sRes, lSpawn, FALSE, sTag);
SetLocalObject(oArea, sKey + "_Obj", oSpawn);
}
}
}
/* respawn loot or other other respawnables */
nSpawns = GetLocalInt(oArea, "Area_Respawns");
if (nSpawns > 0) {
int i, nType, nRespawnTime, nUptime = GetLocalInt(GetModule(), "uptime");
string sKey, sVar;
object oSpawn;
for (i = 1; i <= nSpawns; i++) {
sKey = IntToString(i);
nRespawnTime = GetLocalInt(oArea, "Area_Respawn_" + sKey);
if (nRespawnTime <= 0 ||
nRespawnTime > nUptime ||
GetIsObjectValid(GetLocalObject(oArea, "Area_Respawn_Obj_" + sKey)))
continue;
oSpawn = CreateObject(GetLocalInt(oArea, "Area_Respawn_Type_" + sKey),
GetLocalString(oArea, "Area_Respawn_Res_" + sKey),
GetLocalLocation(oArea, "Area_Respawn_Loc_" + sKey));
SetLocalObject(oArea, "Area_Respawn_Obj_" + sKey, oSpawn);
if ((sVar = GetLocalString(oArea, "Area_Respawn_Var_" + sKey)) != "")
AssignCommand(oArea, DelayCommand(0.0, RestoreLocals(oSpawn, sVar)));
}
}
/* clear despawn setting on area */
if (GetLocalInt(oArea, "DespawnTrack")) {
int nDespawnTime = GetLocalInt(oArea, "DespawnTime");
if (nDespawnTime) {
int nUptime = GetLocalInt(GetModule(), "uptime");
if ((nUptime - 3600) > nDespawnTime) {
DeleteLocalInt(oArea, "DespawnTime");
DeleteLocalInt(oArea, "DespawnCount");
}
}
}
}
LMK if you have any questions. "uptime" is incremented in the mod heartbeat.
Funky