noxworld-dev / opennox

OpenNox main repository.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scripts should be able to set immunities for NPCs/monsters

Ephreaym opened this issue · comments

I need a function to make it so that Warriors can't be stunned but get slowed instead. However, when stunned through a trap or ghost the stun should take effect.

It seems this feature is shared by large monsters. Maybe if I can set the subclass of the war bot to large_monster it'll get this feature? Not sure how else to resolve this issue. Since I don't know how to differentiate between regular stun and trap/ghost stun.

Or am I missing something?

I'm using this at the moment to make them immune to stun.

if war.unit.HasEnchant(enchant.HELD) {
ns.CastSpell(spell.SLOW, war.unit, war.unit)
war.unit.EnchantOff(enchant.HELD)
}

But it's a problem for the Ghosts attack and stun from a trap.

Ah, and of course when the warrior bots miss their charge they need to be stunned.

Three direction where we could take this:

  1. Set some flag on the object so that it acts like a large monster.
  2. Add a special "before enchant" event that will have enchant reason passed to it.
  3. Add some new generic immune system (enchant + source/reason).

The first one would be the easiest, but I don't think I want to allow that before we figure out how it's used in the engine. Subclass is tightly coupled with the data structures and setting the wrong one will likely make it crash at some point. So let's avoid that as long as we can.

Second option is the most flexible - scripts decide what happens on each enchant. However this puts the script functions inside the main loop of the engine, which may cause performance issues long-term. So the third option is an alternative that is more performant.

Third option may work by setting "immune" flags for the object. For example, something like this:

// Enables immune for all sources
obj.SetEnchantImmune(enchant.HELD, source.Trap | source.Spell | source.Ability | source.Weapon)
// Only immune to weapon effect
obj.SetEnchantImmune(enchant.HELD, source.Weapon)
// Disable immune.
obj.SetEnchantImmune(enchant.HELD, 0)

What is cool about this is that we could use similar system for immune to spells/damage types.

Would that be flexible enough? Any other ideas of how it might look like?

If we can differentiate between the source that'd work!

This sounds like a silly question, but I'll ask it anyway:
What in the game's codes depicts a Warrior player apart from a Conjurer or Wizard player? Shouldn't we be looking there, and find a way to apply the Warrior player's codes to NPCs?

@KILAH4716 That's the right call, but the engine does it really in ad-hoc manner, like "if the object is a player and is a warrior ...". I don't really want to find all spots which does this check and add another one like "if the object is a monster and is an NPC and it's marked as warrior by the script" - this is a bit too much.

For us it's easier to make one generic system where any object can get these kind of immune protections. So engine would only need to check: "if object (whatever it is) has immune". This gives much more freedom for scripts and future mods.

Fixed with coding through adding booleans and conditions to check for bomber collision.

if war.unit.HasEnchant(enchant.HELD) && !war.abilities.BerserkerStunActive && !war.abilities.BomberStunActive {
			ns.CastSpell(spell.SLOW, war.unit, war.unit)
			war.unit.EnchantOff(enchant.HELD)
		}

I'd still like to keep it open to track the immunity system implementation. Still think it's a good idea to have something like this. Will rename the ticket.

After speaking with had_zeng, we think that it would be nice to also add things like damage resist that is controlled by scripts.

For example:

// Set 20% damage resist from fire (from weapons and traps)
obj.SetDamageResist(damage.FIRE, 0.2, source.Trap | source.Weapon)