Question about battle in my module

I’m working on the end battle in my module at the moment. I’m a bit afraid that it might be too much for the game to handle. At the moment there are 43 enemy creatures there and about 25 allies that are going to fight. Will that work or will the whole thing just crash? I will also do a script where all these enemies change faction from Commoner to Hostile in one script. Will that also make the game crash perhaps?

I guess I could just try it out, but I thought to ask you experts out there if there are limits to this.

There’s not much else going on in the area. It’s just a 12x12 outdoor area with quite a few trees and a field.

my guess is that’s pushing it, but would probably work on a decent machine. A bit laggy maybe … idk

graphical effects from spells will likely be the most significant performance inhibitor. So if there’s not many casters that’s a bonus …

the way to improve performance is to use custom creature-blueprints that don’t have the full regalia of ai-scripts slotted. Ie, just enough to start a fight with an opponent and choose another when that fight ends, etc.

calls to DetermineCombatRound() could even be replaced with a small custom core-ai routine, one that considers only talents that the creatures will actually have.

 
If a fair bit of this were done, my feeling is that the engine could handle combat with hundreds of creatures. Because the truth is the regular ai-scripts, from this perspective, muddle their way though hundreds of conditions and determinations that wouldn’t amount to a hill of beans in generic mass combat,

ps. I thought Pain wrote such scripts … but i cant find 'em  :\

pps. Changing faction of a hundred creatures is insignificant – it’s what happens after the faction change occurs that matters  o.O

1 Like

Thanks for the reply, kevL_s!

As it is now, I only use custom creature blueprints here, but there are a quite a few spellcasters. Are there scripts that I could take out fully from the list of scripts of each character (that would help with performance), or is it the OnDamage, OnDeath stock scripts and so forth that just need heavy editing perhaps?

With my limited knowledge of scripting, I guess fiddling too much with those stock scripts might cause even more damage to the game/module than not fiddling with it, I guess.

@kevL_s - Would this be something I could use perhaps:

https://neverwintervault.org/project/nwn2/script/battle-system

i’d say even that’s too complicated

consider this. Remove all of the ai-scripts from all those custom NPC blueprints and assign this to their heartbeats:

// 'combat_hb'
/*
    Heartbeat script that executes DCR against the nearest threat.
*/

const string VAR_TARGET = "Target";

void main()
{
    object oSelf = OBJECT_SELF;

    int iAction = GetCurrentAction(oSelf);
    if (   iAction != ACTION_ATTACKOBJECT
        && iAction != ACTION_CASTSPELL
        && iAction != ACTION_TAUNT)
    {
        ClearAllActions();

        object oThreat = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY,
                                            oSelf, 1,
                                            CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN,
                                            CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE);
        if (GetIsObjectValid(oThreat))
        {
            SetLocalObject(oSelf, VAR_TARGET, oThreat);
            ExecuteScript("dcr", oSelf);
            DeleteLocalObject(oSelf, VAR_TARGET);
        }
    }
}

and this to their OnDamaged:

// 'combat_da'
/*
    Damaged script that executes DCR against the damager.
*/

const string VAR_TARGET = "Target";

void main()
{
    object oSelf = OBJECT_SELF;

    int iAction = GetCurrentAction(oSelf);
    if (   iAction != ACTION_ATTACKOBJECT
        && iAction != ACTION_CASTSPELL
        && iAction != ACTION_TAUNT)
    {
        ClearAllActions();

        object oThreat = GetLastDamager(oSelf);
        if (GetIsObjectValid(oThreat) && GetIsEnemy(oThreat, oSelf))
        {
            SetLocalObject(oSelf, VAR_TARGET, oThreat);
            ExecuteScript("dcr", oSelf);
            DeleteLocalObject(oSelf, VAR_TARGET);
        }
    }
}

and this is the support-script for those

// 'dcr'
/*
    Executable script to avoid bloating the other AI-scripts with
    calls to DetermineCombatRound().

    Requires that a local object "Target" be set on OBJECT_SELF.
*/

#include "nw_i0_generic"

const string VAR_TARGET = "Target";

void main()
{
    DetermineCombatRound(GetLocalObject(OBJECT_SELF, VAR_TARGET));
}

With that set up, all you should need to do is run your script that changes faction … I’m betting you’d get a pretty decent mass combat just from that. But there’s lots of room for tweaks, to prevent ganging up or to attack lastattacker, etc. The nice thing about DetermineCombatRound() is that it handles casters.

( leave the party with their regular ai-scripts ofc )

 
tested w/ 40 melee + 1 caster no lag at all

3 Likes

Wow! Thank you so much, @kevL_s! I’ll try that.

1 Like

i also set their perception range to Long – but it depends on what you got going in the area. You could have one creature wander up, spot the enemy … and that starts everything idk

Alright, one thing I don’t quite get here. The support script. Where do I put that, or what do I do with that?

endb

Am I to put “Target” at Variables perhaps and then…?

I’ll set perception to Long, no problem. The way I thought to do this is: The PC and companions arrive on sight and have a short conversation with the main baddy, then the whoe thing starts by executing a script where all the baddies change faction to hostile.

Ah, wait, I think I get it. Your support script is supposed to be named “dcr” right? And that gets called in both the other scripts?

1 Like

Just a thought: Maybe I should let the main baddy have all the normal scripts? I mean, he is to talk to the characters…Maybe removing all the other standard scripts will screw that up?

1 Like

I’ve tested the battle now. It seems to work really well. I have a lot of spellcasters but I can see no lag at all. One thing I noticed though. I have trolls as enemies, and they are not possible to kill at the moment with these scripts. It’s because you can only kill them with acid and fire, so I suspect it’s got something to do with that.

Edit: Noticed that they have the gb_troll_dmg script on their OnDamage so I change from your script to this on those two trolls I had there.

Edit2: I must say I’m really impressed with your scripts here. The battle is running very smoothly. Even though there are lots of spells thrown around there’s no lag. Amazing. Thank you again, @kevL_s!

3 Likes

I was going to say I used the battle system before and it worked well, but it looks like kevL solved the problem.

2 Likes

battle system looks pretty cool but i figured andgalf just wanted to whack it with a stick and make it work …

2 Likes

LOL! Probably, yes. I just wanted something to work, and to me it doesn’t seem like there’s something important missing when looking at the fights. What would have been different if I had kept all the stock scripts?

each creature’s OnPerception would be checking if it should play ambient animations … or be checking if it should go wandering off in search of invisible creatures … or if it should bash down a door …

or if distillable loot should be created OnDeath … or shout to its allies to attack its killer …

or if it should OnSpawn as an Incorporeal mob …

etc.

2 Likes

Any kind of area visual effects could still bring the scene to its knees.

I have another area which causes the game to crash every now and then. I think it might have to do with quite a lot of visual effects in the area. It’s an outdoor area too, a town to be precise. I’m using the X2_L_SPAWN_USE_AMBIENT variable on a lot of the NPCs. The only thing most of them need to do in this area, is to be able to walk around and talk to the characters. Could one strip all the characters of all their “slot scripts” there perhaps? Would they still be able to walk around and turn towards the PC when he talks to them, and start a conversation?

I think walking is handled by WalkWayPoints() in the OnHeartbeat script, and dialog is handled by BeginConversation() in the OnConversation script.

again you could clear out a lot of stuff …

that’s just a check in one of the ai-scripts, OnHeartbeat iirc.

nwn2 crashes are very difficult to debug; it can be a time-consuming trail and error process of elimination, unless ya get lucky …

2 Likes

Then I should, in what I can deduce from what you’re saying, be able to clear (take away) the scripts for OnBlocked, OnDamaged, OnDeath, OnEndCombatRound, OnInventoryDisturbed, OnPerception, OnPhysicallyAttacked, OnRested,OnSpawn and OnUserDefined, right?

1 Like