Jump to content


Photo

Commander Attachment AI


19 replies to this topic

#1 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 01 March 2006 - 03:15 AM

Okay, this took me a while to get working in any form.

How does the AI know when to attach things? How does it deattach? A quick lesson for us all...

Firstly, certain things run on a squad. A squad is each seperate entity on the battlefield which can be selected.

This was my first hurdle of understanding, that, in fact, commanders when attached cannot be got at except through a few info functions such as GetAttachedHealthPercentage() and an important HasSquadAttached().

So, when a squad has a commander attach, the squad's AI determines when the commander de-attaches.

Also, this means we cannot check stat info of the attached unit, since they are not a seperate squad, they don't have gettable names, stats (eg: ranged, stances) or suchlike.

-------------

There are some additional problems with the AI code. Namely, some useful information, such as if a unit is unbreakable, are unavailable (things like squad size, "rating" and suchlike are available). A shame.

-------------

So this is what I'm working on:

- A table set via. the squad's ID, when they are attached to by a commander unit, with ranged and stance information, as well as a special field "keep_attached", which if true, will never deattach the unit.

- An additional (table) input for TryAttachSquad(), called something like best_attach_unit. Possibly the table will include some stats to check for, or requirements for attaching to the best squad. Range limits still apply of course. This code would allow the farseer to attach (permanently) to seer councils, for instance. Will get this table to be priority based - possessed marines over khorne beserkers for instance.

- Will add a way to make sure units stay attached to a commander for a greater amount of time. Units attaching then suddenly detaching just because the current battle is over is counter productive sometimes.

- Might detach during combat, need to look into switching to a really close, better CC squad if the commander is in CC.

- Will attach some ranged heroes to ranged squads mostly permanently (eg: Sorceror, who is a bit weak in CC)

- Broken squads will not automatically get deattached, since the commander might just be better off staying with them for a few more seconds (especially with space marines).

- Only named, primary heroes (in the exsisting hero table to be precise) would have permanent fixtures applied.

- Might attach melee commanders to (primarily) ranged (but still good/mediocre in CC) units if there are a few around, to provide some cover for the commander (eg: Space Marines, Chaos Space Marines, Cultists, Shootas, Guardians).

- Might attach ranged commanders to primarily melee units, and set the squad to range, if there are a lot of them. For example, Khorne Beserkers do have pistols, as well as Banshee's, Sluggas, Nobz, etc. Could happen when damaged (it was meant to according to the code before anyway), but this might happen before combat.

- TryAttachSquadMelee() should be revamped to allow a commander to look for specific squads first.

Perhaps most importantly, besides the permanent fixtures mentioned:

- Commanders might well attach well before combat with good or large units, meaning they are ready with a good unit as cannon fodder/backup right away and provide bonuses before hitting enemy units. Also groups commanders with the army better.

---------------------

I will post code changes later if I can get some of the stuff working well. It'd mean changes to each commander's specific AI files, but that'd not matter too much.

I will look into the tables info, and see if some decent logic can be decided on how commanders attach to units and how they deattach according to conditions.

Will also see if we can have the race code "race"infantrytatics.ai file, return "moraleimmune" function as true if an actual unbreakable unit (EG: Khorne Beserkers).

A lot to do? not much, to long winded. Any suggestions on how you attach commanders, and how the AI should, would be welcome. Might as well get it right first time.

#2 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 01 March 2006 - 03:30 AM

Also, what time unit does GetGameTime() return? I'll be attempting to use it somehow :cool:

#3 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 01 March 2006 - 07:09 AM

It returns ticks since gamestart. There are 8 ticks a second.

#4 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 01 March 2006 - 01:23 PM

Thanks, will look into making them attach for a decent amount of time out of combat, or something.

Is there a good way to check if the squad or commander is in an attack run? (they are obviously not attacking otherwise). If there is a good way, I'll add in code for commanders to possibly find a decent squad to attach to for the duration of the attack.

#5 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 01 March 2006 - 03:28 PM

You can use IsInStateAttackMove() to figure out if he's in an attack run.

#6 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 01 March 2006 - 07:03 PM

Thanks, I'll see what changes (however "strange" they might act in some circumstances) I can do.

Basically, I want to get it to a state of workingness :blush: then I'll work on making the code work better.

#7 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 12 March 2006 - 01:53 PM

Okay, I might as well post some of the code I've got so far:

Infantry tatic.ai changes:


-- FD additional code
-- This table holds information on the commander attached to us, and if they want to stay attached.
InfantryTactic.AttachedInfo = {}

-- FD: Returns true if we have a specific hero attached - ie: Force Commander, Librarian, never Apothecary.
function InfantryTactic:CommanderAttached()

   if self.squad_ai:IsAttached() then

	   for i in self.commander do

		  if self.squad_ai:HasSquadAttached( self.commander[i][1] ) then
			   return true
		   end
	   end
   end

   return false
end


--[[
	Finaldeath:
	Need to rework.

	This is called each update call, on squads with commanders attached to them.

	Will:
	- Detach a healthy commander unit if squad is now not in combat and not recently hurt.
	- Will not detach dying (<50% health) heroes
	- Will not detach ranged heroes if a ranged squad

	If detached:
	- Sets stance back to default (eg: get a melee hero attached to a ranged squad, and was melee stance,
	  will now set back to ranged stance)

	Changes:
	- Keep some squads always attached
		- Farseer + Seer council
		- Terminators + Force commander
		etc.

	- Possibly detach a commander in combat if there is a better squad they could attach too?

	Useful functions:

	- float GetAttachedHealthPercentage(void)

	- bool HasSquadAttached( const char* squad_name )

	Can check for specific commanders attached to us.
]]

function InfantryTactic:CheckForDetach()

	--print("InfantryTactic:CheckForDetach FOR: "..self.stats:GetSquadName() )

	-- FD: New code

	-- Match such as GetID() of the squad, and the unit we have got attached to us.
	-- The table array InfantryTactic.AttachedInfo[our_id][INFONAME] contains extra info about why the commander attached
	-- and what the commander is like.
	local our_id = self.stats:GetID()

	-- Get commander attached to us. Might be an empty string if not a primay commander attached to us.
	local commandername = self:GetNameOfAttachedCommander()

	-- FD: Will not detach if we have not reached time limit
	if( cpu_manager.cpu_player:GetGameTime() < InfantryTactic.AttachedInfo[our_id]["time_limit"] ) then

		--print("InfantryTactic:CheckForDetach | IGNORING: Not reached time yet | us: "..self.stats:GetSquadName()..": attached name (might be invalid): "..commandername)

		return nil
	end

	-- FD: Will not detach if we are:
	-- - In combat
	-- - Being attacked
	-- - Attacking someone
	if( self.squad_ai:IsInStateAttackMove() or self.squad_ai:IsInCombat() or self.squad_ai:WasRecentlyHurt() ) then
		-- Do no switching in combat or when taking damage

		--print("InfantryTactic:CheckForDetach | IGNORING | us: "..self.stats:GetSquadName()..": attached name (might be invalid): "..commandername)

		return nil
	end

	-- Check if we have a primary commander attached. Means a valid commandername field.
	if commandername == "" then
		-- No *primary* commander attached, we therefore ignore more checks FOR NOW.

		return nil
	end

	-- If we find that we want to stay attached dispite time...
	if( commandername == InfantryTactic.AttachedInfo[our_id]["commander"] and
		InfantryTactic.AttachedInfo[our_id]["keep_attached"] == true) then

		-- We want to stay attached, but is there another (better) unit nearby this commander would attach to?
		-- FD: TODO based on InfantryTactic.AttachedInfo[our_id]["best_attach_units"] table

		-- ...we want to keep this commander attached forever, nevermind morale, health or otherwise.
		return nil
	end

	-- FD:  Will detach if we are healthy
	-- 		OR we are a melee squad (ranged squads wait for the 50% health theshold, but if damaged and in a melee squad,
	--		commanders should not get involved in melee!)
	if( self.squad_ai:GetAttachedHealthPercentage() > 0.5 or not self.squad_ai:IsRanged() ) then

		-- Are we broken? (at the moment) always detach
		if ( self.squad_ai:IsBroken() ) then
			-- Detach
			self:DetachOurAttachment()

			return nil
		end

		-- Are we capturing something? always detach if healthy/melee
		if ( self.squad_ai:IsCapturing() ) then
			-- Detach
			self:DetachOurAttachment()

			return nil
		end

		-- If melee unit then we will detach if our commander isn't melee
		if ( not self.squad_ai:IsRanged() and InfantryTactic.AttachedInfo[our_id]["is_ranged"] == true ) then
			-- Detach
			self:DetachOurAttachment()

			return nil
		end
	end

	return nil

	-- FD: Old code
--[[
	-- If not in combat and not recently hurt
	if (not self.squad_ai:IsInCombat() and not self.squad_ai:WasRecentlyHurt()) then

		-- We will detach healthy commanders, with 50% or more health.
		-- Any ranged units will not detach commanders from them.
		if (self:CommanderAttached() and (self.squad_ai:GetAttachedHealthPercentage() > 0.5 or not self.squad_ai:IsRanged())) then
			self.squad_ai:DoDetachSquad()
			self.squad_ai:DoSetDefaultMeleeStance()
		end
	end
]]
end

-- FD: Wrapper function,
-- No way to delete hashed table entries. This might do something with the table (like "clear the entry") perhaps however.
function InfantryTactic:DetachOurAttachment()


	print("InfantryTactic:DetachOurAttachment | us: "..self.stats:GetSquadName()..": attached name (might be invalid): "..self:GetNameOfAttachedCommander())


	-- Do the detachment
	self.squad_ai:DoDetachSquad()
	self.squad_ai:DoSetDefaultMeleeStance()
end

-- FD: This will return the unit name who is attached to us
function InfantryTactic:GetNameOfAttachedCommander()

	if self.squad_ai:IsAttached() then

		for i in self.commander do

			if self.squad_ai:HasSquadAttached( self.commander[i][1] ) then
				return self.commander[i][1]
			end
		end
	end

	-- Return empty string on none
	return ""
end

Tatic.ai changes:


--[[
	How this works:

	- This is called from commander's tatic files.

	- Then, once attached, cannot be called again (they are part of a new squad).

	- When attached to a squad, that squad will call CheckForDetach()

 	Attempts to attach us to a squad.
	TryAttachSquad ( melee, match_stance, radius, min_strength, health )

		melee - If TRUE we attach to melee squads primarily, if FALSE we attach to ranged squads first.
 		melee_stance - If TRUE we must attach to the value above. If FALSE, we will use the other option as a secondary option.
 		radius - Distance we can attach to squads in meters
 		min_strength - Minimum squad strength to attach too
 		health - the % health we should be at to attach


	TryAttachAssassinate()
		Will always attempt an attach with anything nearby to survive.


	TryAttachSquadMelee()
		  Will attach to squads within 10M if in combat.

	See also:
	InfantryTactic:CheckForDetach
		Will *detach* unless a ranged attachable unit (which is set on all things like apothecarys, commissars, etc)
		- Need to also sort
eg:

   -- force commander
   --assassinate win condition -- always attach to a squad
   if cpu_manager.assassinate then

	  self:TryAttachAssassinate()
   else
	  --state machine
	  if not InfantryTactic.Update( self ) then
		 return
	  end

	  if self:TryAttachSquad( false, true, 50, nil, 0.4 ) == nil then

		 self:TryAttachSquadMelee()
	  end
   end

   -- librarian
   if self:TryAttachSquad( false, true, 50, nil, 0.5 ) == nil then

	  self:TryAttachSquadMelee()
   end

   --apothecary
   self:TryAttachSquad( false, false, 1000, 250, nil )

  Need revamping

	Possible ideas:
	- Add in morale stats to all units. Units who are immune to morale damage can get attached to.
	- Attach always to high rated units nearby.
	- Always attach to benificial/prefered units
		- Farseer + Seer Council (Possibly Banshees, gains spell time decrease from seer council)
		- Force Commander, Librarian + Terminators (Possibly only assault ones)
		- Chaos Lord + Possessed Space Marines, Khorne Beserkers (Morale immunity, Melee orientated)
		- Sorceror + Marines, Possed, Beskerkers. (Maybe more of a ranged hero? Morale immunity is good though)
		- Warboss or Warboss + Nobz, Sluggas (Group ork bonuses, waagh power, teleporter, cannon fodder)
		- (does this already) Any IG secondary hero, apothecarys, bad doks - always attach!
	- Stay attached for a minimum amount of time
	- Attach if we are very near to a matching stance squad and are in combat anyway.
	- Do not deattach if on a broken squad. Usually this hinders morale regen since the commander and squad can be hit
	  seperately.

	AIMS:
	- Attach some commanders much more early then combat situations and stay together
		- Especially with Farseer, etc.
	- Late game, always attach early (since most commanders die quite fast otherwise)
	- Squads with commanders should reinforce more
	- Can attach to morale immune squads to gain benifit if broken
	- Do not keep switching squads in combat unless really good one is nearby.
	- Some heroes should properly attach to ranged squads as a preference to melee
	  squads, and not change the stance of the squad to melee (eg: sorceror, librarian
	  with word of the emporer, farseer with spells or low health).

	- If at low HP, will attach to a ranged squad to recover health, and stay at ranged stance.

	Useful functions:

	- bool IsAttached( Void )

	- function CpuManager:GetClosestSquad( pos, range, functor )

	NB: The function GetClosestSquad() isn't going to be too good for getting the best general unit to attach to
	in combat. It mainly gets the nearest.



	If attached:
]]
function Tactic:TryAttachSquad( melee, match_stance, radius, min_strength, health, best_attach_unit )

	--print("Tactic:TryAttachSquad | us: "..self.stats:GetSquadName())

	-- Finaldeath rewrite

	-- Will:
		-- Attach if broken
		-- Attach at full health
		-- Match up units specifically

	--[[

self.stats:GetSquadName() == "ork_squad_mek_boy"

	]]

	-- Who we attach to
	local attach_to = nil

	-- FD: Always attach to certain squads we love even if broken or not low HP
	if best_attach_unit ~= nil then

		-- Best attach unit is a table
		for i = 1, table.getn(best_attach_unit) do

			-- Filters squads for the exact best squad
			local special_filter = function( squad_ai )
				return (squad_ai:GetSquadName() == best_attach_unit[i]) and
					self.squad_ai:CanAttachTo( squad_ai ) and
					not squad_ai:IsCapturing() and
					not cpu_manager:InSubState( squad_ai:GetID() )
			end

			-- Find something
			attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), radius * 2, special_filter )

			-- If we have something found...
			if attach_to ~= nil then

				print("Tactic:TryAttachSquad | us: "..self.stats:GetSquadName().."| Attaching to SPECIAL: "..attach_to:GetStats():GetSquadName())

				-- ...attach
				self:DoMoveAttach( attach_to, true, best_attach_unit )

				-- We will possibly force stance change
				if match_stance then
					if(melee) then
						attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Assault )
					else
						attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Ranged )
					end
				end

				-- Stop now
				return attach_to
			end
		end
	end

	-- If broken
	if self.squad_ai:IsBroken() then

		-- If broken, try and attach to any nearby unbreakable squads (ie: IsAffectedByMorale())

		-- NB: Need to make sure we can check who is immune to morale proper - engineers
		-- get IsAffectedByMorale() set to FALSE if and only if they are building or something.
		-- and no where else I can tell this is functions return value is changed.

		-- FD: Use IsBroken for now

		-- Filters squads for the exact best squad
		local unbreakable_filter = function( squad_ai )
			return not squad_ai.IsBroken and -- not squad_ai.infantrytactic:IsAffectedByMorale() and
				self.squad_ai:CanAttachTo( squad_ai ) and
				not squad_ai:IsCapturing() and
				not cpu_manager:InSubState( squad_ai:GetID() )
		end

		-- Find something
		attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), 20, unbreakable_filter )

		-- If we have something found...
		if attach_to ~= nil then

			print("Tactic:TryAttachSquad | us: "..self.stats:GetSquadName().."| Attaching to UNBROKEN: "..attach_to:GetStats():GetSquadName())

			-- ...attach
			self:DoMoveAttach( attach_to )

			-- We will possibly force stance change
			if match_stance then
				if(melee) then
					attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Assault )
				else
					attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Ranged )
				end
			end

			-- Stop now
			return attach_to
		end
	end


	-- We will attach if:
	-- - We are not broken
	-- - We have less then "health" percent health
	if ( (not self.squad_ai:IsBroken() and (health == nil or self.squad_ai:GetHealthPercentage() < health)) or
	-- Special case: Attach early to correct squad if we are in tier 3 or 4 and are in combat
		((self.squad_ai:IsInCombat() and cpu_manager:GetTierLevel() == 3) or cpu_manager:GetTierLevel() == 4) )	then

		-- Minimum strength of squad we want to attach to
		-- 	- Always have a minimum if none is supplied, although a 0 input is valid.
		if min_strength == nil then
			min_strength = 160 + (cpu_manager:GetTierLevel() - 1) * 40
		end

		-- Filters squads for ranged units only
		local range_filter = function( squad_ai )
			return	squad_ai:GetProRatedCost() >= min_strength and
				self.squad_ai:CanAttachTo( squad_ai ) and
				squad_ai:IsRanged() and
				not squad_ai:IsBroken() and
				not squad_ai:IsCapturing() and
				not cpu_manager:InSubState( squad_ai:GetID() )
		end

		-- Filters squads for melee units only
		local melee_filter = function( squad_ai )
			return	squad_ai:GetProRatedCost() >= min_strength and
				self.squad_ai:CanAttachTo( squad_ai ) and
				not squad_ai:IsRanged() and
				not squad_ai:IsBroken() and
				not squad_ai:IsCapturing() and
				not cpu_manager:InSubState( squad_ai:GetID() )
		end

		-- Attach to ranged units
		if not melee then

			-- Find ranged squad
			local attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), radius, range_filter )

			-- Try for melee unit if we don't care about the stance
			if attach_to == nil and not match_stance then
				-- Find melee squad
				attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), radius, melee_filter )
			end

			-- If we have something found...
			if attach_to ~= nil then

				print("Tactic:TryAttachSquad | us: "..self.stats:GetSquadName().."| Attaching to RANGED: "..attach_to:GetStats():GetSquadName())

				-- ...attach
				self:DoMoveAttach( attach_to )

				-- We might have attached to a melee unit. Force this unit to be a ranged stance.
				if match_stance then
					attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Ranged )
				end

				-- Stop now
				return attach_to
			end

		-- Attach to melee units
		else

			-- Find melee squad
			local attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), radius, melee_filter )

			-- Try for ranged unit if we don't care about the stance
			if attach_to == nil and not match_stance then
				-- Find ranged squad
				attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), radius, range_filter )
		 	end

			-- If we have something found...
			if attach_to ~= nil then

				print("Tactic:TryAttachSquad | us: "..self.stats:GetSquadName().."| Attaching to MELEE: "..attach_to:GetStats():GetSquadName())

				-- ...attach
				self:DoMoveAttach( attach_to )

				-- We might have attached to a ranged unit. Force this unit to be a melee stance.
				if match_stance then
					attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Assault )
				end

				-- Stop now
				return attach_to
			end
		end
	end

	-- Return either nil, or the squad we attached to.
	return attach_to
end

--[[

This obviously is useful if we are in melee and really should be attached...

Need to revamp a bit:
- Attach to things depending on if we are really close and might as well (IE: they are not bad at melee)

- Do more things then just attach at 30% health. At 70% we might want to attach to a very nearby squad.

- Since this assumes all heroes are melee heroes (sets the squad's melee stance to assault), it will actually
  do worse for some heroes who could play well at range. Must alter that.

  - Attach ranged based heroes to ranged squads nearby even if they are not strong enough if in combat/being attacked.

- Some checks if we are defending or attacking, or even doing neither, might be a good idea.
]]

-- Attach to something in combat.
function Tactic:TryAttachSquadMelee()

	--if I'm in combat
	if not self.squad_ai:IsBroken() and self.squad_ai:IsInCombat() then

		-- If we have health % < 30% we are dying
		if self.squad_ai:GetHealthPercentage() < 0.3 then

			-- Attach to melee *or ranged* units nearby based on if they are not busy or broken. Attach to anything!
			local attachable_filter = function( squad_ai )
				return self.squad_ai:CanAttachTo( squad_ai ) and
					not squad_ai:IsBroken() and
					not squad_ai:IsCapturing() and
					not cpu_manager:InSubState( squad_ai:GetID() )
			end

			-- Find close by squads. 10M range.
			local attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), 10, attachable_filter )

		else -- Else, Health > 30%

			-- Attach to melee units nearby based on if they are not busy or broken
			local melee_filter = function( squad_ai )
				return self.squad_ai:CanAttachTo( squad_ai ) and
					not squad_ai:IsRanged() and
					not squad_ai:IsBroken() and
					not squad_ai:IsCapturing() and
					not cpu_manager:InSubState( squad_ai:GetID() )
			end

			-- Find close by squads. 10M range.
			local attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), 10, melee_filter )
		end

		-- If we find a squad...
		if attach_to ~= nil then

			print("Tactic:TryAttachSquadMelee | us: "..self.stats:GetSquadName().." | Attaching to: "..attach_to:GetStats():GetSquadName())

			-- ...attach...
			self:DoMoveAttach( attach_to )

			-- and set the stance of the squad to Assault.
			attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Assault )
		end
	end

	-- No return?
end

-- This will always attach our Will to most any squad available to stay alive...after all, "Fire at will";-)
function Tactic:TryAttachAssassinate()

	-- Filter
	-- Almost any squad (ranged, or melee), that isn't broken or capturing, and is 200 or higher rating.
	local attachable_filter = function( squad_ai )
		return squad_ai:GetProRatedCost() >= 200 and
			self.squad_ai:CanAttachTo( squad_ai ) and
			not squad_ai:IsBroken() and
			not squad_ai:IsCapturing()
	end

	-- Find a squad in a 60M range.
	local attach_to = cpu_manager:GetClosestSquad( self.squad_ai:GetPosition(), 60, attachable_filter )

	-- Attach to one if we find any
	if attach_to ~= nil then
		-- Attach
		self:DoMoveAttach( attach_to )
		-- Do not melee attack with this squad
		attach_to:DoSetMeleeStance( SquadAI.MSTANCE_Ranged )
	end
end

--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------

-- FD: Altered
-- This will set attachment information
-- Pass in keepattached to be TRUE if the attaching commander should stay, if they match the commander name that is
function Tactic:DoMoveAttach( attach_to, keepattached, best_attach_units )

	-- Search table InfantryTactic.KeepAttached
	-- Match such as GetID() of the squad, and the unit to keep attached
	local attach_to_id = attach_to:GetStats():GetID()

	-- Default keepattached to false
	if keepattached == nil then
		keepattached = 0
	else
		keepattached = 1
	end

	-- print the table
	print("Tatic:DoMoveAttach: Attempting to add ID:"..attach_to_id..": to table, with name:"..self.stats:GetSquadName())


	-- This is our commander attachemnt information hash.
	--  - Why hash: Using the ID would mean we have a million empty entries up to "ID", loverly!
	InfantryTactic.AttachedInfo[attach_to_id] = { }

	-- Add to the squad's ID, the commander name, and if we want to keep him on forever.
	InfantryTactic.AttachedInfo[attach_to_id]["commander"] = self.stats:GetSquadName()
	InfantryTactic.AttachedInfo[attach_to_id]["keep_attached"] = keepattached

	--print("|| ADDED:"..InfantryTactic.AttachedInfo[attach_to_id]["keep_attached"].."|| should equal :"..keepattached.."||")

	-- Add in our stance and ranged information too
	InfantryTactic.AttachedInfo[attach_to_id]["is_ranged"] = self.squad_ai:IsRanged()
	InfantryTactic.AttachedInfo[attach_to_id]["stance_melee"] = self.squad_ai:GetMeleeStance()
	InfantryTactic.AttachedInfo[attach_to_id]["stance"] = self.squad_ai:GetStance()

	-- Add in the info from what the commander likes to attach to if valid
	if best_attach_units ~= nil then
		InfantryTactic.AttachedInfo[attach_to_id]["best_attach_units"] = best_attach_units
	end

	-- Keep units attached for a minimum amount of time to stop them detaching too fast
	-- - 120 seconds (2 minutes)
	InfantryTactic.AttachedInfo[attach_to_id]["time_limit"] = cpu_manager.cpu_player:GetGameTime() + (8 * 120)

	-- print all!
	--table.foreach(InfantryTactic.KeepAttached, print)

	-- print the table
	print("Attaching the commander: "..self.stats:GetSquadName()..": to: "..attach_to:GetStats():GetSquadName())

	-- Do also attach :-D
	self.squad_ai:DoAttachSquad( attach_to )
end

--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------



Example of changed tatics file, for mekboy:

----------------------------------------
-- File: 'mekboytactic.ai'
-- Edited by Thudmeizer @ 09.03.2005
-- Edited by LarkinVB   @ 16.08.2005

class 'MekBoyTactic' (OrkInfantryTactic)

MekBoy = {}

function MekBoyTactic:__init( squad_ai ) super( squad_ai )

end

function MekBoyTactic:UpdateAbilities()

	if MekBoy.zap_id == nil then
		MekBoy.zap_id = cpu_manager.stats:GetAbilityID( "ork_tank_zappa" )
	end

	if MekBoy.superstick_id == nil then
		MekBoy.superstick_id = cpu_manager.stats:GetAbilityID( "ork_superstick_bomb" )
	end

end

function MekBoyTactic:IsAttacker()

	--assassinate win condition -- never attack
	return not cpu_manager.assassinate

end

function MekBoyTactic:GetName()
	return "Mek Boy Tactic"
end

function MekBoyTactic:DoAbilities()

	MekBoyTactic.UpdateAbilities(self)

	Ability.DoAbilityTarget( self.squad_ai, MekBoy.zap_id, Ability.Filters.CloseVehicleEnemy )
	Ability.DoAbilityTarget( self.squad_ai, MekBoy.superstick_id, Ability.Filters.CloseVehicleEnemy )

end

function MekBoyTactic:Update()

	if self:IsComplete() then
		return
	end

	--assassinate win condition -- always attach to a squad
	if cpu_manager.assassinate then

		self:TryAttachAssassinate()
	else

		--state machine
		if not InfantryTactic.Update( self ) then
			return
		end

		best_attach_units = { "ork_squad_nob", "ork_squad_slugga" }

		if self:TryAttachSquad( false, true, 50, nil, 0.3 ) == nil then

			self:TryAttachSquadMelee()
		end
	end
end

Have still not added IsInStateAttackMode() and commanders sometimes attach to some things they would be better off not attaching too.

NB: this is beta 12 code, but beta 13 shouldn't be any different. Note the extra print statements might slow AI operation a bit ;) and its not optimised yet at all. Just showing some progress.

Edited by Finaldeath, 12 March 2006 - 01:55 PM.


#8 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 16 March 2006 - 01:26 AM

Okay, Larkin or Arkhah, I'd love to know if this was possible:

- If a commander is attached to a squad they will stay on, to always set aside some resources, if no desperate research is taking place, to fill the squad to full strength - or at least half strength.

- Possibly only when attacking/defending.

I have seen (with b13) a ork army with a total pop of 9, which later went to 13 as this happened, having their one, new, killa kan, upgrading to a missile launcher.

Of course, there was no commander, but more boyz were needed at that point as opposed to upgrades, heh.

Maybe this is more hinging on the general AI.

anyway, it equally applies to other armies. If a Chaos Lord attached to some beserkers, the bonuses induced would be better if the squad is larger/constantly reinforcing. Farseer gains a massive bonus from seer councils etc.

Basically, I wondered if a way of having a "save resources for certain reinforments/upgrades" could be initiated and used anywhere.

#9 ThetaOrion

ThetaOrion

    title available

  • Members
  • 676 posts

Posted 16 March 2006 - 01:56 AM

I hope I'm not butting in where I'm not wanted, or where it will get anyone angry.

But, one of the most popular suggestions for fixing the 1.41 Orks is to double the potential size of the Tank Busta Squad. The Orks need something to take out all those Space Marine tanks, IG Tanks, and Eldar Fire Prisms, since the Ork Tanks don't have what it takes. But, the Ork Tank Busta Squads are always killed long before they kill any tanks.

Of course, some have suggested that purposefully attaching a Big Mek or an Ork WarBoss to a squad of Tank Bustas might be a way for the Tank Busta Squad to last just barely long enough to take down a tank.

Making the Ork Waagh Banners tougher with more hit points and making them do more damage so that they are as good as any turret is another suggestion. In that Soul Forge game I played with B13, I lost a couple of Waagh Banners and suddenly I could no longer make tanks. I mean, nobody else loses their ability to make tanks if you destroy their turrets.

Anyway, ever since 1.41, whenever I want a hard game, I put Orks on my side, and whenever I want an easy game at the HARD setting, I put Orks on the enemy's side. And, that doesn't even count when I play as the Orks. I just have a devil of a time lasting long enough to get a win playing as the Orks, with something like B13 or B12. So, anything you can do to make the Ork AI play more perfectly or more efficiently over the long haul would indeed be a step in the right direction.

The Orks do really well on average with B13 on the smaller maps where they can get into close combat melee quickly and do their damage. It's on the bigger or more intricate maps that the 1.41 Plain Vanilla stuff comes shining through and the Orks fall down. I mean in PV 1.41, the Orks have nothing at all that can stand up to Tier 4 Space Marines and actually hold their own let alone win.

Anyway, I hope Arkhan and Thud have time to look at FinalDeath's input here and elsewhere, because I think he is right on track when it comes to his comments about the Orks and the Chaos, and maybe if something could be squeezed into the Final Release to give them a bit more End Game final tier teeth, that might not be a bad thing. I am seeing some of this show up in the larger map longer games that I just started testing with B13.

Edited by ThetaOrion, 16 March 2006 - 02:03 AM.


#10 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 18 March 2006 - 03:55 PM

I am still waiting guys for an answer, surely you didn't ignore this thread?

Is there any way to priorise or set aside resources for squad reinforcement?

#11 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 18 March 2006 - 04:50 PM

At the moment there's no really priority/ressource management behind the upgrades and reinforces. It's definetly possible, but the code has to be expanded to check all available upgrades/reinforces and then take the best one.

#12 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 18 March 2006 - 05:33 PM

Right, then I'll add that to my to do list of things to investigate ;)

Its a bit useless sometimes a commander attaching to a nice, newly built squad, and then it just getting blown away since it has no upgrades (eg: power claws) or seargents (eg: aspiring champions on cultists) or even a complete squad (eg: few sluggas).

Main reason is for the units that have teleport (mekboy, sorceror, other new races), that have a bonus for multiple amounts (seer council), or have a good weapon or are powerful anyway (nobz, assault terminators :p ).

Glad its possible, if it isn't implimented I'll look into it but it'd require more knowledge then I have currently to do anything about it.

#13 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 18 March 2006 - 08:08 PM

It is not possible to get what upgrades a squad already has afaik.

#14 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 18 March 2006 - 09:50 PM

It is possible, Larkin, to know it has or hasn't got them by simple maths, which I know you already know :p

I'll likely add into the code some checks to make sure units with upgrades (which are ranged squads) do not get attached to unless at the "Low health and don't want to die" stage.

For melee units though, nobz/sluggas/etc., upgrades for a warboss/mekboy squad (latter especially) helps ;)

Any suggestions welcome. Some of my current choices might not be too appropriate in games that I don't play often or races I rarely play as for instance.

#15 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 19 March 2006 - 08:49 AM

It is possible, Larkin, to know it has or hasn't got them by simple maths, which I know you already know

You can determine that a SM squad with some injured members has two plasma and a rocket + a flamer by simple math ? I'm curious, please explain.

#16 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 19 March 2006 - 12:21 PM

You get its total value. You divide this by the number of objects in its squad. If this doesn't match the cost of one unit * number of objects in squad, then there should be heavy/special weapons/upgrades.

Of course, I havn't written the code for it so I'm not sure al the parts are there yet.

#17 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 19 March 2006 - 02:48 PM

But you don't know the type of upgrades and you have to take into account that the squad value decreases with damage taken. If a unit looses health the value decreases even while the number of troopers stay the same. Together with variables like squad leaders with updates modifying the value too and the fact that you have to extract cost of single trooper/leader/upgrades from lua I'm really looking forward to your solution.

#18 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 19 March 2006 - 06:28 PM

I'll look into it but it might not be perfect :blush:

#19 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 19 March 2006 - 07:39 PM

I personally had something different in mind. Check all squads and let the best one make its upgrades or reinforces. Reinforcing an obliterator squad is probably more important than reinforcing a cultist squad. That's what I meant!

#20 Finaldeath

Finaldeath
  • Project Team
  • 188 posts
  • Location:UK

Posted 19 March 2006 - 07:56 PM

I knew that Arkhan :blush:

...And, Arkhan, reinforcing a squad with a commander attached which "should be" reinforced (IE: this is the best squad possible we can attach to, so beef it up!), like Nob squads, terminators, seer councils and possessed marines, would take priority over just "the best" outright, I should think :)

I need to know how to get upgrades so commanders don't attach to ranged units with special weaponry, which means usually they are too far out of range to fire thier own gun.

Edited by Finaldeath, 19 March 2006 - 07:57 PM.




Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users