Deleted56253002User Posted March 29, 2021 Share Posted March 29, 2021 (edited) 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 March 29, 2021 by Guest Link to comment Share on other sites More sharing options...
maxarturo Posted March 30, 2021 Share Posted March 30, 2021 (edited) - '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 March 30, 2021 by maxarturo Link to comment Share on other sites More sharing options...
Deleted56253002User Posted April 2, 2021 Author Share Posted April 2, 2021 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 AutoActor Property Soldier2 AutoActor Property Soldier3 AutoActor Property Soldier4 AutoActor Property Soldier5 AutoActor Property Soldier6 AutoActor Property Soldier7 AutoActor Property Soldier8 AutoActor Property Soldier9 AutoActor Property Soldier10 AutoActor Property Soldier11 AutoActor Property Soldier12 AutoActor Property Soldier13 AutoActor Property Soldier14 AutoActor Property Soldier15 AutoActor 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()endIfEndEvent 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!") endIfendEvent Link to comment Share on other sites More sharing options...
maxarturo Posted April 2, 2021 Share Posted April 2, 2021 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 More sharing options...
xyz3lt Posted April 6, 2021 Share Posted April 6, 2021 (edited) 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 April 6, 2021 by xyz3lt Link to comment Share on other sites More sharing options...
Deleted56253002User Posted April 9, 2021 Author Share Posted April 9, 2021 This is very helpful, I will go on to test it. Thanks! Link to comment Share on other sites More sharing options...
Deleted56253002User Posted April 10, 2021 Author Share Posted April 10, 2021 (edited) 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 April 10, 2021 by Guest Link to comment Share on other sites More sharing options...
Recommended Posts