(FAQ) More ideas for heroes spawning troops (never give up!)

In this forum you will find and post information regarding the modding of Star Wars Battlefront 2. DO NOT POST MOD IDEAS/REQUESTS.

Moderator: Moderators

User avatar
[RDH]Zerted
Gametoast Staff
Gametoast Staff
Posts: 2982
Joined: Sun Feb 26, 2006 7:36 am
Projects :: Bos Wars AI - a RTS game
Games I'm Playing :: SWBF2 and Bos Wars
xbox live or psn: No gamertag set
Location: USA
Contact:

Post by [RDH]Zerted »

I haven't used any of the matrix functions, but I've spawned alive units, dead units, and changed their classes. So far there hasn't been any problems unless you try to do it online when you're not the host, in which case you become 'disconnected' with your unit. All the player controls stop working and you can't kill yourself. You can fly around in free camera and see yourself (sometimes 2 or 3 of you if you attempt it a couple times) but no one else in the server can see or hit your unit.

What code have you been using with SetEntityMatrix()? To teleport someone, I've been killing them then respawning them at a different pathpoint.
archer01

Post by archer01 »

This is the function I've been using to move things around:

Code: Select all

function MoveEntityToNode(entIn,pathIn,nodeIn)
	if not entIn then
		print("Warning!: Entity not specified for move")
		return false
	elseif not pathIn then
		print("Warning!: Path not specified for Entity " .. entIn .. " move")
		return false
	end
	
	local node
	if nodeIn then
		node = nodeIn
	else
		node = 0
	end
	
	local locDest = GetPathPoint(pathIn,node)
	local charUnit = GetCharacterUnit(entIn)
	if charUnit then
		SetEntityMatrix(charUnit,locDest)
		return true
	end
	return false
end
Now mind you I've edited this function slightly since it was originally part of a larger object (class), so I've changed the function declaration (from ***:name to name) and the print statements for the error message to simple prints instead of using the object's speciallized error message function to let it run by itself. Those changes shouldn't cause anything different to happen, but I like to be completely honest about these types of things to avoid mis-communications.

The function returns true of false depending on where it got to in the code. This is NOT a sure fire way of telling if the character was actually moved, but it's better than nothing.




Another a question Zerted: You said that if a non-host activates some of these functions it messes up the character controls. I thought that only the host's computer processed the lua script and the clients simply interacted with it (so anything done in a mission lua will be fine). Am I wrong in that assumption? Were you referring to your shell script work by any chance, since it runs on each system independantly?
User avatar
[RDH]Zerted
Gametoast Staff
Gametoast Staff
Posts: 2982
Joined: Sun Feb 26, 2006 7:36 am
Projects :: Bos Wars AI - a RTS game
Games I'm Playing :: SWBF2 and Bos Wars
xbox live or psn: No gamertag set
Location: USA
Contact:

Post by [RDH]Zerted »

When testing things, I just create a fake console command for it. This lets me test it on any map, in SP or MP, and as host or not. Its easier than using a test map.
somen00b

Post by somen00b »

archer01 wrote:
Hidden/Spoiler:
This is the function I've been using to move things around:

[code]function MoveEntityToNode(entIn,pathIn,nodeIn)
if not entIn then
print("Warning!: Entity not specified for move")
return false
elseif not pathIn then
print("Warning!: Path not specified for Entity " .. entIn .. " move")
return false
end

local node
if nodeIn then
node = nodeIn
else
node = 0
end

local locDest = GetPathPoint(pathIn,node)
local charUnit = GetCharacterUnit(entIn)
if charUnit then
SetEntityMatrix(charUnit,locDest)
return true
end
return false
end[/code]

Now mind you I've edited this function slightly since it was originally part of a larger object (class), so I've changed the function declaration (from ***:name to name) and the print statements for the error message to simple prints instead of using the object's speciallized error message function to let it run by itself. Those changes shouldn't cause anything different to happen, but I like to be completely honest about these types of things to avoid mis-communications.

The function returns true of false depending on where it got to in the code. This is NOT a sure fire way of telling if the character was actually moved, but it's better than nothing.




Another a question Zerted: You said that if a non-host activates some of these functions it messes up the character controls. I thought that only the host's computer processed the lua script and the clients simply interacted with it (so anything done in a mission lua will be fine). Am I wrong in that assumption? Were you referring to your shell script work by any chance, since it runs on each system independantly?
Could this script be triggerd with something other then a path node for locDest? If yes you could have a theoretical script that when called would move a unit to something you just dispensed's postion. You could call it with oncharacterdispensepowerup and have the first part be a delay. Lifespan or lua would destory the object when it's purpose is done.

For single player you could use entity 0 (the player) as the point with a Z offset, g2g more later...
archer01

Post by archer01 »

From my post before the one you quoted:
archer01 wrote:Assuming there is nothing wrong with setting a matrix of a unit "on-the-fly" if you will, couldn't you spawn a character beside another character with the following code?:

Code: Select all

local HeroEntity = blah
local SomeUnspawnedCharacter = blah2
local destination = GetEntityMatrix(GetCharacterUnit(HeroEntity))
SpawnCharacter(SomeUnspawnedCharacter,destination)
The "HeroEntity" and "SomeUnspawnedCharacter" would just be the entity identifiers (example: the player in instant action is always entity zero).

[...]

I would also like to try to see if I can get the CreateMatrix() function working. I'm guessing that will allow you to make a path point during runtime (but again, I don't know for sure).
GetEntityMatrix() and GetPathPoint() should return the same type of data: A matrix with position coordinates and a direction vector.
somen00b

Post by somen00b »

sry, I know little lua+I didn't have time to think. I would test that script if you told me what to enter for the variables. I think some position modification (why did I say offset?) would be good so you don't spawn one thing inside another. It would look better that way. But it's not a big deal.
User avatar
jangoisbaddest
Lieutenant General
Lieutenant General
Posts: 661
Joined: Mon Feb 27, 2006 12:10 am
Projects :: No Mod project currently.
Games I'm Playing :: I have not listed any games yet
xbox live or psn: No gamertag set
Location: All Along The Watchtower

Post by jangoisbaddest »

Branching off of your teleportation method, do you suppose it's possible to teleport AI? If so, it's 100x better than an elevator. I'm working (slowly) on a boarding party map, and I want you to be able to get into the command towers, but having a normal path there wouldn't be realistic (it would take forever, and would be un - realistic to the ship's layout). So what I propose is this: you make 2 regions and two paths, and two rooms that both look like elevators. When a unit (player or AI) enters on of the regions, it teleports them to the corrisponding path, right in front of the opposite "elevator" room. It wouldn't interrupt the battle or screw up the AI, and it would be an way to relistically include the bridge area inside the capital ship! So is it possible to have AI be teleported to a path by entering a region?
archer01

Post by archer01 »

Yah, it's the same teleport code.

Using the function above, it would go like this:

Code: Select all

OnEnterRegion(
	function(regIn,character)
		MoveEntityToNode(character,"pathName")
	end,
	"regionName"
	)
	ActivateRegion("regionName")
Or if you only wanted the AI to teleport (ie have the elevator but have the AI skip it):

Code: Select all

OnEnterRegion(
	function(regIn,character)
		if not IsCharacterHuman(character) then
			MoveEntityToNode(character,"pathName")
		end
	end,
	"regionName"
	)
	ActivateRegion("regionName")
Now mind you, I've only just "tested" teleporting guys around. While I haven't noticed any issues yet, there might be some applications where it won't work as expected (i.e. I can't test all situations you might use this stuff, so there might be something I'm missing relating to pathing or something). So you'll have to just try it out yourself and see if it works okay.

Good luck! :D
User avatar
jangoisbaddest
Lieutenant General
Lieutenant General
Posts: 661
Joined: Mon Feb 27, 2006 12:10 am
Projects :: No Mod project currently.
Games I'm Playing :: I have not listed any games yet
xbox live or psn: No gamertag set
Location: All Along The Watchtower

Post by jangoisbaddest »

Thanks! AI planning shouldn't be a problem, because I'll have the elevator "room" in the direction of the bridge CP, and have the planning graph end in the room. That should carry them to the region, which will take them to a brand - new network of planning. Hopefully I'll be able to test this out within the next day or so, and if I can, I'll post here again.
somen00b

Post by somen00b »

Teleporting on it's own is great and all, but can we not completly lose the subject of spawning troops on the fly? maybe have a seperate thread for teleporting for other purposes?
archer01

How to create AI-Controlled spawned units

Post by archer01 »

Okay then, how's this:

Code: Select all

-- Setup the team that will spawn in ScriptInit(), include the SetTeamAsFriend() stuff
	-- Add this code into ScriptPostLoad() once for each team that can spawn stuff (changing a couple of variables each time)
	-- Add an AIGoal for the spawned team somewhere in ScriptPostLoad() so the spawned character will actually do something
	
	TroopSpawnerWeapon = "cis_weap_inf_remotedroid_ord"

	OnCharacterDispenseControllableTeam(
		function(character,controlled)
			if GetEntityClass(controlled) == GetEntityClassPtr(TroopSpawnerWeapon) then
				local SupportTeam = 3 --Team the new spawned character is in (change this)
				local teamSize = GetTeamSize(SupportTeam)
				for i = 0, teamSize-1 do
					local characterIndex = GetTeamMember(SupportTeam, i)
					local charUnit = GetCharacterUnit(characterIndex)
					if not charUnit then
						local destination = GetEntityMatrix(GetCharacterUnit(character))
						SpawnCharacter(characterIndex,destination)
					end
				end
			end
		end,
		CIS --User team (change this)
		)
This spawns the whole team that is specified.
Here are some screens (Team 3 had only 10 members and didn't have an AIGoal so they just stood there):
Image
Image

Now before you ask, offsetting the spawn point may not be possible. If the matrix is a "lua table" it might be changable, but if it is "user data" only the exe will understand and be able to edit it.

I'll leave it to you guys to modify it so only so many are spawned at a time. Also, you might consider making it watch for powerups instead of controllables, but that's your choice. Have fun.
somen00b

Post by somen00b »

It works! Set up a team as explained in the ambush turtorial (you don't need the ambush trigger) and bingo!

Here is are some odfs that spawns the units while looking like the guy only moved his hand:

weapon:
Hidden/Spoiler:
[code]
[WeaponClass]
ClassLabel = "remote"

[Properties]
//IconTexture = "HUD_com_probedroid_health_icon"

MuzzleFlash = "small_muzzle_flash"
Discharge = "small_smoke_effect"

RoundsPerClip = "0"
ReloadTime = "0.0"
LockOnRange = "80.0"
LockTime = "0.4"

HeatPerShot = "1.0"
HeatRecoverRate = "0.05"

ZoomMin = "0.0"
ZoomMax = "0.0"
ZoomRate = "0.0"

//AnimationBank = "grenade"
OffhandWeapon = 1

SwitchImmediately = "0"

FireAnim = "1"
InstantPlayFireAnim = "1"

ShotDelay = "1.4"
MinSpread = "0.0"
MaxSpread = "0.0"
AutoAimSize = "1.0"

SalvoCount = "1"
SalvoDelay = "0.0"
InitialSalvoDelay = "0.3"

FireSound = "com_weap_inf_remotedroid_fire"
FireEmptySound = "com_weap_inf_ammo_empty"

OrdnanceName = "ordinance_here"
[/code]
ordinance:
Hidden/Spoiler:
[code]
[GameObjectClass]
ClassLabel = "droid"
GeometryName = "com_weap_probedroid.msh"

[Properties]
ExplosionName = "all_weap_inf_remotedroid_exp1"
GeometryName = "com_weap_probedroid"
ImpactEffectWater = "com_sfx_watersplash_ord"

FLYERSECTION = "BODY"
VehicleType = "light"

PilotType = "remote"

MapTexture = "troop_icon"
HealthTexture = "HUD_com_probedroid_health_icon"
MapScale = 1.0

MapViewMin = 50
MapViewMax = 50
MapSpeedMin = 0
MapSpeedMax = 100

CollisionScale = 10.0

MaxHealth = 100.0
AddHealth = -1.0

EnergyAutoRestore = -99999.9

SetAltitude = 2000.0
GravityScale = 1.0//2
LiftSpring = 10.0 //10Lighter the veh the high the number
LiftDamp = 3.0

ScanningRange = 30.0
TransmitRange = 300.0

Acceleration = 25.0
Deceleration = 3.0
Traction = 22.0
ForwardSpeed = 3.5
ReverseSpeed = 3.5
StrafeSpeed = 0.25

SpinRate = 1.5
TurnRate = 1.5
TurnFilter = 5.0
PitchRate = 2.0
PitchFilter = 5.0
BankAngle = 0.0
BankFilter = 0

MoveTension = "30.0"//how much swim the craft has from the center of the screen


LevelSpring = 5.0
LevelDamp = 3.0

EyePointOffset = "0.0 0.5 0.0"
TrackOffset = "0.0 -0.25 1.8"
TiltValue = "5.0"

DestructTrackOffset = "0.0 0.0 18.0"
DestructTiltValue = "10.0"
DestructChargeEffect = "com_sfx_weap_remotedroidcharge2"

PitchLimits = "-50.0 50.0"
YawLimits = "-0.0 0.0"
AimerPitchLimits = "-90 90"
AimerYawLimits = "-90 90"

WEAPONSECTION = 1
WeaponName = "com_weap_null"
WeaponAmmo = 0
WeaponChannel = 0

AISizeType = "SOLDIER"

AmbientSound = "remotedroid_engine_lp"
Ambient2Sound = "remotedroid_radio"
HurtSound = ""
DeathSound = ""

\\\\\\\\\\\\ Collision \\\\\\\\\\\\\\

BuildingCollision = "p_buildingsphere"
VehicleCollision = "p_buildingsphere"
OrdnanceCollision = "p_sphere"
SoldierCollision = "p_sphere"
[/code]
Change to suit your needs, and lastly, THANK YOU archer01!
User avatar
Teancum
Jedi Admin
Jedi Admin
Posts: 11080
Joined: Wed Sep 07, 2005 11:42 pm
Projects :: No Mod project currently.
Games I'm Playing :: Destiny
xbox live or psn: No gamertag set
Location: Indiana

Post by Teancum »

This stuff should be put on the Wiki. Kudos to you all! :D
somen00b

Post by somen00b »

I think an addon that makes any points the spawned troops earn go to the player who spawned them (or there team) would be a good for using this in assault mode. Basically any points team x earns goes to the player who spawned the troops or team y. If it's possible :D
User avatar
jangoisbaddest
Lieutenant General
Lieutenant General
Posts: 661
Joined: Mon Feb 27, 2006 12:10 am
Projects :: No Mod project currently.
Games I'm Playing :: I have not listed any games yet
xbox live or psn: No gamertag set
Location: All Along The Watchtower

Re:

Post by jangoisbaddest »

somen00b wrote:I think an addon that makes any points the spawned troops earn go to the player who spawned them (or there team) would be a good for using this in assault mode. Basically any points team x earns goes to the player who spawned the troops or team y. If it's possible :D
Sorry to bump this topic, but a while ago I sucessfully implemented a hero that both spawns troops from a local team AND gives the hero health if one of those from team 3 gets a kill. This code can be easily adjusted to give that player or their team a point assuming you know the function that accesses player (character) points or team points, respectively. Anyway, here is my code (and this works 100%, it is ingame and functions properly):

Code: Select all

--This function makes sure the hero gets health if his spawned troops get a kill.

OnCharacterDeath(
	function(player, killer)
		if not killer then
			--print("suicide.")
			return
		end
		if GetCharacterTeam(killer) == 3 then
			local heroTeam = 2
			local teamSize = GetTeamSize(2)
			local heroUnit = GetCharacterUnit(killer)
			local isHeroFound = 0
			for i = 0, teamSize-1 do
				--print (i)
				local characterIndex = GetTeamMember(2, i)
				local charUnit = GetCharacterUnit(characterIndex)
				--print(characterIndex)
				--print(charUnit)
				--Make sure that the team player is not dead, and thus has an associated unit
				if charUnit then
					--print("Character has a unit. Checking class for hero match.") 
                                	if GetEntityClass(charUnit) == FindEntityClass("ksh_hero_oom9") then
						--print("Player using hero class found!")
						heroUnit = charUnit
						isHeroFound = 1
                                        	i = teamSize - 1 --docs say no break statement in LUA ><
					end
				end
			end
			if isHeroFound == 0 then
				--print("Could not find a hero unit ingame.")
				return
			end
			local heroHealth = GetObjectHealth(heroUnit)
			--Now we make sure that we don't give him more health than his max health
			if heroHealth >= 1451 then --assuming the hero has 1500 health
				SetProperty(heroUnit, "CurHealth", 1500)
				--print("Hero restored to max health.")
			else
				SetProperty(heroUnit, "CurHealth", heroHealth + 50)
				--print("Hero gained 200 health")
			end
		end
	end
)
Post Reply