public static void endStench(GameObject caster, int spell_id) { var casterId = 1; if ((caster != null)) { casterId = Co8.getObjVarNibble(caster, STATE_VAR, CID); Logger.Info("Cleaning up and ending stench for {0} id={1}", caster, casterId); } else { Logger.Info("Caster is null now, trying default"); caster = SelectedPartyLeader; // just to get a location } foreach (var critter in ObjList.ListVicinity(caster.GetLocation(), ObjectListFilter.OLC_CRITTERS)) { if ((Co8.getObjVarNibble(critter, STATE_VAR, casterId) != STATE_UNPROCESSED)) { removeStenchEffect(casterId, spell_id, critter, STATE_UNPROCESSED, true); } if ((Co8.getObjVarNibble(critter, STATE_VAR, casterId) != STATE_NEUTRALISED)) { Co8.setObjVarNibble(critter, STATE_VAR, casterId, STATE_UNPROCESSED); } } return; }
// Give the critter an effect object with the appropriate effect. public static void applyStenchEffect(int casterId, int spell_id, GameObject critter, int status) { var stench_obj = getStenchObj(critter); if ((stench_obj != null)) { if ((status == STATE_NAUSEA)) { // Check current stench effect. var effectOwnerId = Co8.getObjVarNibble(stench_obj, EFFECT_VAR, CID); var effectStatus = Co8.getObjVarNibble(stench_obj, EFFECT_VAR, effectOwnerId); if ((effectStatus == STATE_SICKNESS)) { // Take ownership of effect since Nausea trumps Sickness. Logger.Info("caster {0} taking ownership of effect from caster {1} on {2}", casterId, effectOwnerId, critter); var effectVar = Co8.getObjVarDWord(stench_obj, EFFECT_VAR); stench_obj.Destroy(); stench_obj = createStenchObject(spell_id, critter, status); Co8.setObjVarDWord(stench_obj, EFFECT_VAR, effectVar); } } } else { stench_obj = createStenchObject(spell_id, critter, status); } // Set the status & id into the effect var. Co8.setObjVarNibble(stench_obj, EFFECT_VAR, CID, casterId); Co8.setObjVarNibble(stench_obj, EFFECT_VAR, casterId, status); return; }
public static void removeStenchEffect(int casterId, int spell_id, GameObject critter, int status, bool unNullify) { var stench_obj = getStenchObj(critter); if ((stench_obj != null)) { Logger.Info("removing effect {0} for {1} by caster {2}", stench_obj, critter, casterId); Co8.setObjVarNibble(stench_obj, EFFECT_VAR, casterId, status); // Check current stench effect. var effectOwnerId = Co8.getObjVarNibble(stench_obj, EFFECT_VAR, CID); if ((casterId == effectOwnerId)) { // Pass ownership of effect to another stench. int s = 0; int otherId; for (otherId = BASECASTERID; otherId < 7; otherId++) { s = Co8.getObjVarNibble(stench_obj, EFFECT_VAR, otherId); if (s == STATE_NAUSEA || s == STATE_NAUSEA_HANGOVER) { break; // Nausea trumps Sickness. } } var effectVar = Co8.getObjVarDWord(stench_obj, EFFECT_VAR); stench_obj.Destroy(); if (s == STATE_NAUSEA || s == STATE_NAUSEA_HANGOVER || s == STATE_SICKNESS) { Logger.Info("caster {0} taking ownership of effect from caster {1} on {2}", otherId, casterId, critter); stench_obj = createStenchObject(spell_id, critter, s); Co8.setObjVarDWord(stench_obj, EFFECT_VAR, effectVar); Co8.setObjVarNibble(stench_obj, EFFECT_VAR, CID, otherId); } if (s != STATE_NAUSEA && s != STATE_NAUSEA_HANGOVER && unNullify) { reenableWeapons(critter); } } } else { reenableWeapons(critter); } return; }
public static void unNeutraliseStench(GameObject critter) { var curedCount = Co8.getObjVarNibble(critter, STATE_VAR, COUNTER); Logger.Info("Un-neutralising stench, curedCount={0}", curedCount); Co8.setObjVarNibble(critter, STATE_VAR, COUNTER, curedCount - 1); if ((curedCount <= 1)) { Logger.Info("Un-neutralising stench on: {0}", critter); for (var casterId = BASECASTERID; casterId < 7; casterId++) { Co8.setObjVarNibble(critter, STATE_VAR, casterId, STATE_UNPROCESSED); } } return; }
public static void neutraliseStench(GameObject critter, int duration) { Logger.Info("Neutralising stench on: {0}", critter); var stench_obj = getStenchObj(critter); if ((stench_obj != null)) { stench_obj.Destroy(); reenableWeapons(critter); } // Add to cured count and set all stench id's to neutralised. var curedCount = Co8.getObjVarNibble(critter, STATE_VAR, COUNTER); Co8.setObjVarNibble(critter, STATE_VAR, COUNTER, curedCount + 1); for (var casterId = BASECASTERID; casterId < 7; casterId++) { Co8.setObjVarNibble(critter, STATE_VAR, casterId, STATE_NEUTRALISED); } // Setup processing for un-neutralisation. StartTimer(1000 * duration, () => unNeutraliseStench(critter)); return; }
// Main stench processing routine. public static void processStench(GameObject caster, int spell_id) { // Get caster ID, initialising if necessary. var casterId = Co8.getObjVarNibble(caster, STATE_VAR, CID); if ((casterId == 0)) { casterId = casterIdNext; casterIdNext = casterIdNext + 1; if ((casterIdNext > 7)) { casterIdNext = BASECASTERID; } Co8.setObjVarNibble(caster, STATE_VAR, CID, casterId); } // While caster is alive, concious and not destroyed or off. // print "checking caster... flags= ", caster.object_flags_get() & 0xff, " anded=", (caster.object_flags_get() & (OF_DESTROYED | OF_OFF)) if ((caster.GetStat(Stat.hp_current) > -10 && (caster.GetObjectFlags() & (ObjectFlag.DESTROYED | ObjectFlag.OFF)) == 0)) { Logger.Info("Starting stench processing for {0} id={1} spell_id={2}", caster, casterId, spell_id); foreach (var critter in ObjList.ListVicinity(caster.GetLocation(), ObjectListFilter.OLC_CRITTERS)) { if ((critter.GetStat(Stat.hp_current) <= -10)) { Co8.setObjVarNibble(critter, STATE_VAR, casterId, STATE_NOPROCESS); } // Get critter status and process appropriately. var status = Co8.getObjVarNibble(critter, STATE_VAR, casterId); if ((status == STATE_UNPROCESSED)) { // Unprocessed - process critter init, and assign state. if ((critter.IsMonsterSubtype(MonsterSubtype.demon) || critter.IsMonsterCategory(MonsterCategory.elemental) || critter.IsMonsterCategory(MonsterCategory.undead) || critter.GetStat(Stat.level_monk) > 10 || critter.GetStat(Stat.level_druid) > 8)) { // Unaffected critters. (demons, elementals, undead, classes immune to poison) Logger.Info("{0} unaffected", critter); status = STATE_UNAFFECTED; } else if (has_necklace(critter)) { Logger.Info("{0} unaffected", critter); status = STATE_UNAFFECTED; } else if ((inStenchArea(caster, critter))) { // In stench area - attempt save, apply the stench and take ownership. status = attemptSave(caster, spell_id, critter, status); applyStenchEffect(casterId, spell_id, critter, status); } else { // Not yet in stench area. Logger.Info("{0} not yet in stench area", critter); status = STATE_NOTINSTENCH; } } else if ((status == STATE_NOTINSTENCH)) { // Check cured count. var curedCount = Co8.getObjVarNibble(critter, STATE_VAR, COUNTER); if ((curedCount > 0)) { Logger.Info("{0} has been cured, skipping round", critter); Co8.setObjVarNibble(critter, STATE_VAR, COUNTER, curedCount - 1); } // Check if now in stink area. else if ((inStenchArea(caster, critter))) { // In stink area - apply the stench effect. Logger.Info("{0} now in stench area, attempting save", critter); status = attemptSave(caster, spell_id, critter, status); applyStenchEffect(casterId, spell_id, critter, status); } } else if ((status == STATE_SICKNESS)) { // Check if now out of stink area. if ((!inStenchArea(caster, critter))) { Logger.Info("{0} now out of stench area, removing sickness", critter); status = STATE_NOPROCESS; removeStenchEffect(casterId, spell_id, critter, status, false); } } else if ((status == STATE_NAUSEA)) { // Check if now out of stink area. if ((!inStenchArea(caster, critter))) { status = STATE_NAUSEA_HANGOVER; var hangoverCount = RandomRange(0, 3); var stench_obj = getStenchObj(critter); if ((stench_obj != null)) { Logger.Info("{0} now out of stench area, changing to nausea hangover, count= {1}", critter, hangoverCount); Co8.setObjVarNibble(stench_obj, EFFECT_VAR, casterId, status); Co8.setObjVarNibble(stench_obj, COUNT_VAR, casterId, hangoverCount); } else { Logger.Info("Error: Can't find spell object for nausea."); status = STATE_NOTINSTENCH; // In case of error. } } } else if ((status == STATE_NAUSEA_HANGOVER)) { var stench_obj = getStenchObj(critter); if ((stench_obj != null)) { // Check if now back in stink area. if ((inStenchArea(caster, critter))) { Logger.Info("{0} now back in stench area, changing back to nausea", critter); status = STATE_NAUSEA; Co8.setObjVarNibble(stench_obj, EFFECT_VAR, casterId, status); } else { // Maintain hangover. var hangoverCount = Co8.getObjVarNibble(stench_obj, COUNT_VAR, casterId); Logger.Info("{0} has nausea hangover, count= {1}", critter, hangoverCount); if ((hangoverCount < 1)) { status = STATE_NOTINSTENCH; removeStenchEffect(casterId, spell_id, critter, status, true); } else { Co8.setObjVarNibble(stench_obj, COUNT_VAR, casterId, hangoverCount - 1); } } } else { Logger.Info("Error: Can't find spell object for hangover."); status = STATE_NOTINSTENCH; // In case of error. } } else { continue; } // Store critter status. Co8.setObjVarNibble(critter, STATE_VAR, casterId, status); } // Setup processing for next round. StartTimer(500, () => processStench(caster, spell_id)); } else { Logger.Info("Caster died or expired, ending the stench."); endStench(caster, spell_id); } return; }