Page 1 of 1

Despawning Specific Unit Classes [Solved]

Posted: Sat Mar 21, 2015 3:11 pm
by jedimoose32
Hi everyone.

For my Assassination game mode I've added a feature very similar to GTA where more difficult enemies will spawn and start coming after you the longer you stay detected. It works really nicely and is a lot of fun to play with in-game! However, I want the new, more difficult units to de-spawn after the player has become anonymous again. And I have no idea where to even start.

So here's what I've done to get these units to spawn:
Hidden/Spoiler:
[code]
local adjustGuardStrength = function()
if self.guardDefconLevel == 0 then
self:PrintMe("No stars, all's quiet...")
elseif self.guardDefconLevel == 1 then
self:PrintMe("1 star, all's well...") --at 1 star we don't spawn anyone new because it's just going to be the regular police that are already walking around
elseif self.guardDefconLevel == 2 then
AddUnitClass (self.teamDEF, self.guardClassIndex[2], 4) --at 2 stars I want to add 4 of the second entry in the guardClassIndex table (in my case, a sniper droid)
self:PrintMe("2 stars, better watch out")
elseif self.guardDefconLevel == 3 then
AddUnitClass (self.teamDEF, self.guardClassIndex[2], 2) --at 3 stars I want to add 2 more snipers...
AddUnitClass (self.teamDEF, self.guardClassIndex[3], 4) --and 4 of the third entry in the table, which is the assault droid
self:PrintMe("3 stars, this might hurt a bit")
elseif self.guardDefconLevel == 4 then
AddUnitClass (self.teamDEF, self.guardClassIndex[3], 2) --2 more assault droids at 4 stars...
AddUnitClass (self.teamDEF, self.guardClassIndex[4], 4) --and 4 magnaguards
self:PrintMe("4 stars, better get prayin\'")
elseif self.guardDefconLevel == 5 then
AddUnitClass (self.teamDEF, self.guardClassIndex[4], 2) --2 more magnaguards at 5 stars...
AddUnitClass (self.teamDEF, self.guardClassIndex[5], 4) --and 4 droidekas!!
self:PrintMe("5 stars, aww HELL no!")
else
self:PrintMe("No defcon level?? How?")
end
end
[/code]
Is there a way to essentially highlight all units of a certain class, kill them, and then force them not to spawn again until next time the player gets into trouble? :? I haven't been able to figure out a way to remove a unit class entirely, so far...

Thanks in advance.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 7:38 pm
by [RDH]Zerted
Use a 3rd team that doesn't control any spawn points. Manually spawn the units when you need them. Stop spawning them when you don't or directly kill their unit object.

Look at SelectCharacterClass(), SpawnCharacter(), OnCharacterDeathTeam(), and KillObject().

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 10:34 pm
by jedimoose32
Forgive me for sounding dumb, but wouldn't KillObject expect a string for input, as in the given name of that object?

Edit: Or can I use KillObject(GetTeamMember(team, number)) ?

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 10:44 pm
by Noobasaurus
You'll need to use that along with GetCharacterUnit.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:07 pm
by jedimoose32
KillObject(GetCharacterUnit(GetTeamMember(x,y))) ?

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:08 pm
by Noobasaurus
That should work.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:11 pm
by jedimoose32
While you're here I may as well finally ask someone what kind of information GetCharacterUnit returns. What does it do? If I already have team member 0, for example, why do I need to them get the unit as well?

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:14 pm
by Noobasaurus
It takes a character and uses its information as an object. Some lua functions require the information to be in this form, which is why you have to do this sometimes.

Before you use GetCharacterUnit, it has unit data, which is different. I'm hunting down something to help now.
razac920 wrote:GetCharacterUnit inputs a character (i.e. number) and outputs an object.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:16 pm
by jedimoose32
That makes sense. Thanks.
Edit: So it would make sense in some cases to define said object as a variable? e.g.:
local myUnitObject = GetCharacterUnit(GetTeamMember(2,1))

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:22 pm
by Noobasaurus
Yeah it would make sense to do that to help organize your objects from characters so you can use whichever one you need at any time. It also cuts down on the amount of code whenever you use it.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:27 pm
by jedimoose32
Cool stuff. What I really need is a way to keep track of which team member numbers are alive and which are dead. Because right now if I try and get any information for a dead team member it returns a nil value and a severity 3 error. So far I haven't found a good way to do it.
Edit: What about IsObjectAlive(myTeamObject)? That would return a 0 rather than a nil value, wouldn't it?

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:33 pm
by Noobasaurus

Code: Select all

   unitsAlive = {}

   unitSpawn = OnCharacterSpawn(
    function(character)
        playerInfo = {playerUnit = GetCharacterUnit(character), playerTeam = GetCharacterTeam(character)--, this comma is only necessary if you add more info
                           --any other info you want to record
                         }
        unitsAlive[character] = playerInfo
    end)
I believe this should do it. Zerted wrote this.

And yes, that probably would return a 0.

Re: Despawning Specific Unit Classes

Posted: Sat Mar 21, 2015 11:43 pm
by jedimoose32
I believe I tried implementing this, or something similar, in an earlier version of my current code (back then I didn't have a 'hot zone', the player's anonymity was determined purely by how close he was to a police unit, and it was awesome) but it didn't work, though I may have implemented it incorrectly. What ended up happening is that the game would cycle through the list of team members, and eventually find one that was dead, return a nil value, give me a Sev-3 error, and stop running my code.
The longer I stare at the example code you shared though, the more convinced I am that I must have done it wrong. I could set up an OnCharacterDeath that would use table.remove(unitsAlive[character]) and then have my proximity checker run through unitsAlive in pairs... and there's something I'm missing but I'm at work and can't really think of what that missing piece is... something about GetWorldPosition(unitsAlive[character.playerUnit])... (is that syntactically correct? I'm relatively new to lua tables).

Re: Despawning Specific Unit Classes

Posted: Sun Mar 22, 2015 11:15 am
by razac920
Can you show me your code? It shouldn't be too hard to avoid any function-crashing severity 3 errors.

Re: Despawning Specific Unit Classes

Posted: Sun Mar 22, 2015 12:12 pm
by jedimoose32
I was actually able to get it working last night. :) I'll share that portion of the code later, my computer is currently all packed up.

Re: Despawning Specific Unit Classes

Posted: Sun Mar 22, 2015 6:05 pm
by [RDH]Zerted
I never bothered with IsObjectAlive(). If the player is dead, then GetCharacterUnit() returns nil. Some of the functions accept nils as arguments and some crash when given nils. I never bothered to memorize which ones do which, so I always do a nil check before hand:

Code: Select all

local unit = GetCharacterUnit(player)
If unit == nil then return end --the function ends here if the player is dead
--player is alive if the code reaches this point
or

Code: Select all

local unit = GetCharacterUnit(player)
if unit ~= nil then
    --player is alive, do something here
else
    --player is dead here
end
--player is alive or dead here
I don't recommend storing units in an alive or dead table if it can be avoided. It's probably safe, but we don't know enough about the game's internal threading design. When a unit dies does OnCharacterDeath get called instantly or might some of our other code run beforehand (in which case you'll have a dead player in your alive table). Does a spawned player leaving the server trigger an OnCharacterDeath()? But those are only issues you need to think about if you're trying to make a very high quality map. It's safer to loop through all the units on a team as then you don't have those issues, but I never ran benchmarks and it can depend on what your map is doing.

Lua tables: http://lua-users.org/wiki/TablesTutorial

If you want to see what something returns, just print it out. Almost everything will print out without crashing the game. There's a couple unicode strings that crash the game if you print them.
print("team member", GetTeamMember(1,2));
print("it's unit", GetCharacterUnit(GetTeamMember(1,2));

If you want to look at a table and have v1.3 installed use: uf_print( <table>, <true to print out nested table, else false for just the top level>, <starting depth number (for easier output reading only)> )
If you want to see everything available to you at that point print out Lua's global table (will freeze the game for a couple minutes while it prints everything): uf_print(_G, true, 0)

Re: Despawning Specific Unit Classes

Posted: Sun Mar 22, 2015 6:50 pm
by razac920
I suppose it depends on what you are trying to do. If you want to somehow modify the character unit after death (deactivating it to keep it from vanishing or spawning a unit at its location, for example), then you'd need to keep a table of all the character units beforehand. But yeah, I agree it generally doesn't make sense to keep separate lists for alive units and dead units.

Re: Despawning Specific Unit Classes

Posted: Mon Mar 23, 2015 5:34 pm
by jedimoose32
Thanks for the pointers, Zerted. In this case, given some of the other features that I'm currently implementing in the mod, I'm going to use a unitsAlive table, because I will need to quickly and easily pick out certain units depending on their attributes, and then do something with only those units. I'm not going to use a unitsDead table... dead units will just be removed from the unitsAlive table. Going back to my original question, which has been answered by Zerted and Noobasaurus (thanks!), my current plan is to go through the unitsAlive table in pairs and grab all the guards who are of a certain class, and kill them using KillObject(GetCharacterUnit(character)). I'm assuming that using KillObject on a unit will play their death animation, and I'd rather just have them disappear, so I might just teleport them first and then kill them right away after that, so that to the player it looks nice and clean. We shall see.