Jump to content

[LE] Switch Between AI Packages too slow


Recommended Posts

Whats up everybody.

 

I'm currently working on a major civil war mod that adds thousands of roaming NPCs traveling in Skyrim in groups from 5-22 soldiers. One of the elements that I've added to these groups of patrolling civil war soldiers is an AI package tells the soldiers to retreat back to HQ if soldier X, Y, and Z is dead. This works as intended generally, but many times there is a noticeable inconsistent lag and the "Retreat" AI package will usually take over anywhere from 5-15 seconds after the conditions are met, which in many cases the battle is already lost and in some cases the battle happens so fast that the soldiers don't even attempt to retreat at all, causing un-necessary casualties. I want to know if there is a way to speed it up so that they retreat almost immediately once conditions are met rather than several seconds later when its too late.

 

The other thing I'm currently working on is the ability to command a group of 7-22 friendly CW soldiers (provided you are in the army). I simply made the "Leader" of the group of 7-22 as the potential follower of the player, and had the other 6-21 soldiers following the "Leader" through a follow AI package. The idea is that once the player asks the "Leader" to follow him, the "Leader's" soldiers will also follow as well. I made two follow packages with the conditions as follows:

 

 

 

1. Soldiers will IGNORE combat if "Leader" has their weapon sheathed

(When the player has their weapon sheathed, so will the follower,/"Leader" and the idea is that it also passes onto the rest of the soldiers following the "Leader", basically a command to follow and not engage soldiers, and maintain tightly packed formation. The idea is if the player and his faction come across an enemy in superior numbers and positions, this can allow the player and his army to fallback and retreat to safer/favorable ground and organize, since by default NPCs will never back down from a fight once they detect the enemy, often leading to suicide and un-necessary casualties.)

 

2. Soldiers will NOT IGNORE combat if "Leader" has their weapon drawn

(When the player draws their weapon, the follower/"Leader" will also draw their weapon, prompting the rest of the soldiers to draw their weapon and attack anything that is a threat, basically a command to start attacking. Lets say you are leading a group of 15 sword/shield legionnaires charging 15 enemy Stormcloaks, you would want them to run the "ignore combat" package first so that they DON'T break formation and DON'T scatter and maintain the tightly packed formation so that once you are close, you can draw the weapon (ordering soldiers to attack) and the advantageous positions + focused fire will win you the battle.)

 

The problem is the same as described up above, the AI Packages don't take effect until 5-15 seconds after the conditions are met, which is causing a lot of these issues to occur and making it seem like the soldiers have terrible military discipline and the slowest of reaction speeds. I'd like to know if there is a way to increase the speed at which the game checks AI Package conditions and makes them take effect immediately once conditions are satisfied. I'd also be curious if there is a way to script something like this, it would be cool if once you "Blocked", your followers/fellow soldiers will also block as well as with attacking and bashing of shields, it would make the battle more tactical/strategic and feel like you are leading a disciplined army. To get a better picture of what I'm trying to achieve, check this video out, its from another game but if you could lead the Imperial Legion like this, it would be pretty awesome. I don't have much scripting experience at all but I'd be eager to learn if this is possible.

Edited by Guest
Link to comment
Share on other sites

- 'Conditions' can cause lag on system especially when too many of them are used on too many packages. 'Conditions' uses CPU power and some of them are quite heavy.


- The consistency and speed in which those 'Conditions' get processed and the speed of packages are dependent by 2 things:

a) The amount of things that the CPU & GPU has to process at that particular moment.

b) The power of your PC, the strongest the PC the less likely that you will have any lag.


To speed up the change of packages in some of my mod's scenes and to make them almost instantaneously, i used the function "EvaluatePackage()", either on a script running on the actor itself which controls the actor's abilities "OnCombatStateChanged()", or as the majority of my functions of such, they are controlled by a "Master Controller Script" that handles and monitors everything in order.


Scenes like the one on the video are done with "Quest Scenes", which they are actually "Master Controllers" that handle everything in order and treats everything as one unified entity.

* All of this requires a deep knowledge of scripting, i mean the "Master Controller" logic.



* Keep in mind that the actual control of an npc while is in combat or is threatened, it's very tricky and limited in this game engine.

Unfortunately the actor's combat behavior is exclusively handled by the game's hard coded functions, so to do something like it's shown in the video, requires very good knowledge of the game engine itself, CK and papyrus, but above all an ability to not just think outside the box but to be able to create a whole new box and put the game inside it.


Have a happy modding.

Edited by maxarturo
Link to comment
Share on other sites

So it seems like I got it to work partially thanks to the EvaluatePackage().

 

The package that enables soldiers to attack enemies and draw their weapons happens almost instantaneously.

 

However, the package that disables soldiers and forces them to sheathe their weapons seems to lag behind.

 

Here's the script, and here's a video demonstration:

 

Scriptname questTestingScript extends Quest
Actor Property Commander Auto
Actor Property Soldier1 Auto
Actor Property Soldier2 Auto
Actor Property Soldier3 Auto
Actor Property Soldier4 Auto
Actor Property Soldier5 Auto
Actor Property Soldier6 Auto
Actor Property Soldier7 Auto
Actor Property Soldier8 Auto
Actor Property Soldier9 Auto
Actor Property Soldier10 Auto
Actor Property Soldier11 Auto
Actor Property Soldier12 Auto
Actor Property Soldier13 Auto
Actor Property Soldier14 Auto
Actor Property Soldier15 Auto
Actor Property Soldier16 Auto
Event OnInit()
Debug.MessageBox("The Quest Script is Running")
RegisterForUpdate(1.0)
EndEvent
Event OnUpdate()
if Commander.IsWeaponDrawn()
Soldier1.EvaluatePackage()
Soldier2.EvaluatePackage()
Soldier3.EvaluatePackage()
Soldier4.EvaluatePackage()
Soldier5.EvaluatePackage()
Soldier6.EvaluatePackage()
Soldier7.EvaluatePackage()
Soldier8.EvaluatePackage()
Soldier9.EvaluatePackage()
Soldier10.EvaluatePackage()
Soldier11.EvaluatePackage()
Soldier12.EvaluatePackage()
Soldier13.EvaluatePackage()
Soldier14.EvaluatePackage()
Soldier15.EvaluatePackage()
Soldier16.EvaluatePackage()
endIf
EndEvent
I'm wondering if there's a more efficient way to go about this besides creating an actor property for every single NPC. If there were 50-100 NPCs running this script, how much is it going to impact performance than say if the script was designed differently? I tried playing around with other events in general, but couldn't quite get around to making any of them work, particular those with parameters such as these:
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
if akBaseObject as Weapon
Debug.Trace("This actor just equipped a weapon!")
endIf
endEvent

 

Link to comment
Share on other sites

Now you can see why scenes like the "Civil War" were so poorly made, there is only that much you can do in this game engine.

(That wasn't a civil war, but a gang fight of 10...)


This does not mean that someone couldn't find or invent a way to do it...


* Learn to utilize the "Quest Tool", a lot of things in order to be achieved require a combination of different tools / functions / assets / angles to get it to work.


Good luck.

Link to comment
Share on other sites

Maybe this is what you were looking for?

 

 

 

Scriptname questTestingScript extends Quest  
 
Actor Property Commander  Auto
 
 
Actor Property Soldier1  Auto	;you might want  to turn that into array
Actor Property Soldier2  Auto	;and let actors plot it
Actor Property Soldier3  Auto	;i dunno tho i am just an intern
Actor Property Soldier4  Auto
Actor Property Soldier5  Auto
Actor Property Soldier6  Auto
Actor Property Soldier7  Auto
Actor Property Soldier8  Auto
Actor Property Soldier9  Auto
Actor Property Soldier10  Auto
Actor Property Soldier11  Auto
Actor Property Soldier12  Auto
Actor Property Soldier13  Auto
Actor Property Soldier14  Auto
Actor Property Soldier15  Auto
Actor Property Soldier16  Auto
 
 
Event OnInit()
	 
	Debug.MessageBox("The Quest Script is Running")
	 
	RegisterForAnimationEvent(Commander, "weaponDraw")
	 
EndEvent
	 
Event OnAnimationEvent(ObjectReference akSource, string asEventName) ; When the event of draw weapon occurs
	if asEventName == "weaponDraw"	;if not necessary if weaponDraw is the ony thing you use
		Debug.Notification.("Evaluating all packages.")
		EvaluateAll()
	endif
EndEvent
	 
Function EvaluateAll()
	;Commander.EvaluatePackage() ;?
	Soldier1.EvaluatePackage()
	Soldier2.EvaluatePackage()
	Soldier3.EvaluatePackage()
	Soldier4.EvaluatePackage()
	Soldier5.EvaluatePackage()
	Soldier6.EvaluatePackage()
	Soldier7.EvaluatePackage()
	Soldier8.EvaluatePackage()
	Soldier9.EvaluatePackage()
	Soldier10.EvaluatePackage()
	Soldier11.EvaluatePackage()
	Soldier12.EvaluatePackage()
	Soldier13.EvaluatePackage()
	Soldier14.EvaluatePackage()
	Soldier15.EvaluatePackage()
	Soldier16.EvaluatePackage()
EndFunction

 

 

 

You can also do something like

Soldier1.SheatheWeapon()
Soldier1.EvaluatePackage() 

To make sure the sheathe weapon as soon as possible. Altough if you want to run more than one function on any actor use an array. I am new to papyrus but if i understand correctly Actor arrays aren't native and you have to use PapyrusUtil.ActorArray(int length), i am not sure tho.

Actor[] Soldiers = PapyrusUtil.ActorArray(16)
Soldiers[0] = Soldier1  ;All soldiers can have an actor script that does plotting automatically but thats a bit harder to do
;... 1-14 soldiers here
Soldier[15] = Soldier16


;to run functions on them do a loop
int i 
While i < Soldiers.Length
  Soldiers[i].SheathWeapon()
  Soldiers[i].EvaluatePackage()
  i+=1
endWhile

Anyways i am not exactly qualified to give you advice.

Edited by xyz3lt
Link to comment
Share on other sites

Wow! It worked finally! The soldier now equips AND unequips his weapon based on if the player has their weapon equipped instantly. The part of the script which made all the difference was registering the animation events and creating an event based on those animations, which were "weaponDraw" and "weaponSheathe".

 

RegisterForAnimationEvent(Commander, "weaponDraw")

RegisterForAnimationEvent(Commander, "weaponSheathe")

________________________________________________________________________________________

 

Event OnAnimationEvent(ObjectReference akSource, string asEventName)

if asEventName == "weaponDraw"
Soldier.EvaluatePackage()
endif

 

Event OnAnimationEvent(ObjectReference akSource, string asEventName)

if asEventName == "weaponSheathe"
Soldier.EvaluatePackage()
endif

 

Thanks so much for the help, much is appreciated!

Edited by Guest
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...