Jump to content


Photo

[CLOSED] For NightShift Project - Smart SearchLight Switching


  • This topic is locked This topic is locked
29 replies to this topic

#1 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 22 March 2006 - 09:17 PM

I want to bring this to the current pool of AI coders before it occurs..

I am trying to establish a sub-forum (not password-protected) to faciliate discussion on next-gen DoW/WA AI scripts as well as a hard-nosed learning place to provide solutions to scripting problems in the community.

The format will be the obvious initial message starter explaining the AI scenario if its feasible for the AI to accomplish it either integrated within the existing AI project OR seperately.

An example:

An AI action that allows the AI to toggle a special ability that runs opposite to the way Fleet of Foot runs. The AI would toggle the ability ON during COMBAT and out of combat BUT only turn the ability off when retreating. Supplementing this, the ability(ies) being used reside in the <race>vehicletactic.ai file BUT need to be activated ONLY when the mod is active (a script would need to be created so that the AI would check for a specific ability rgd in the mod's \abilities folder and then run all the abilities that are used ONLY when the mod is active).

I have the existing scripts for above and they work but:

1) I cannot get the AI to turn the ability off when retreating, and
2) Cannot get the AI to only run the abilities in the <race>vehicletactic.ai with the check enabled.

This new sub-forum will be obviously a volunteer-based participation so any help and/or feedback would be fantastic.

Again.. the new sub-forum is for all of us to get ideas on new concepts and to think outside-the-box.

Thanks all!

Edited by thudo, 26 April 2006 - 03:16 AM.

Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#2 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 22 March 2006 - 10:09 PM

1) I cannot get the AI to turn the ability off when retreating, and


You could modify BeginRetreatState() in infantrytactic.ai and vehicletactic.ai. Switch the light off if this method is computed. Then start a timer of maybe 20 seconds to keep the light out for some time.

#3 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 22 March 2006 - 10:14 PM

Thanks Arkhan! With this sub-forum coming.. I think the use of actual scripts to answer will be helpful. I'm nowhere near as good as yourself or Larkin or Excedrin or Corsix with LUA. Theoretical scripting as a response would be absolutely incredible BUT I do not want this exercise to take up too much time: its meant for us all to think a little beyond the scope a little while maintaining our roots.
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#4 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 23 March 2006 - 07:24 AM

I can't see what is advanced, beyond the scope or next-gen with your example.

To be honest I think you just want to open a place were demands of other mods are satisfied by us. This is perfectly fine but you should name it as such :p

Switch the light off if this method is computed.


This is unfair. Arkhan has some secret information and knows you want to switch lights ! Which mod ? :lol:

Again.. the new sub-forum is for all of us to get ideas on new concepts and to think outside-the-box.


If this is really the reason for this forum I'd like to see an example for that.

To answer your question :

Isn't it sufficient to check for IsInStateAttackMove() to toggle it on and IsInStateMove() to toggle it off ?
Usually they are good indicators wether the AI is attacking/retreating.

function SecretRaceVehicleTactic:__init( squad_ai ) super( squad_ai )
	self.lights = false
end

[code]
function SecretRaceVehicleTactic:DoAbilities()

	-- Check if I should toggle mysterious lights
	local lights_id = cpu_manager.stats:GetAbilityID("mysterious_lights")
		if (self.squad_ai:CanDoAbility(lights_id)) then

			 if not self.lights and self.squad_ai:IsInStateAttackMove() then
				 -- switch on
				 self.squad_ai:DospecialAbility(lights_id)
				 self.lights = true
			 elseif self.ligths and self.squad_ai:IsInStateMove()
				 -- switch off
				 self.squad_ai:DospecialAbility(lights_id)
				 self.lights = false
			 end
		end

	-- Call standard method
	VehicleTactic.DoAbilities(self)
end

Edited by LarkinVB, 23 March 2006 - 07:50 AM.


#5 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 23 March 2006 - 01:53 PM

This is for the NightShift Mod and its beyond the scope/next-gen because its not part of the vanilla game. Its thinking outside into new possibilities Relic never considered.

Here are my current scripts - please appraise:

tactic.ai
function Tactic:HasAbility( ability_id )

	-- Get Ability ID
	local iAbilityID = cpu_manager.stats:GetAbilityID( ability_id )

		if (iAbilityID == ability_id ) then
			return true
		end

	return false
end

ability.ai
--toggle searchlight (Not used by Orks)
DoAbilitySearchLight = function( squad_ai, id, msg )

	   if squad_ai:CanDoAbility( id ) and not squad_ai:IsAttached() then

			   local using = squad_ai:IsUsingAbility( id )
			   local combat = squad_ai:IsInCombat()
			   local move = cpu_manager:IsMoving( squad_ai ) or cpu_manager:InSubState( squad_ai:GetID() )
			   if ( using == true and combat == false and move == true) or
				  ( using == false and ( combat == true or move == false) ) then

					   squad_ai:DoSpecialAbility( id )

			   end
	   end
end,

spacemarinevehicletactic.ai
function SpaceMarineVehicleTactic:DoAbilities()

	-- Check if I can use machine spirit while stationary
	if (self.squad_ai:WasRecentlyHurt() and not self.squad_ai:IsInStateMove() and not self.squad_ai:IsInStateAttackMove()) then
		
		local spirit_id = cpu_manager.stats:GetAbilityID( "marines_machine_spirit" )	  
		if (self.squad_ai:CanDoAbility(spirit_id)) then
			self.squad_ai:DoSpecialAbility(spirit_id)
		end	  
	end

		if self:HasAbility( "night_dummy_space_marine" ) == 1 then

	-- Check for SearchLight (Combat = On, No Combat = On, Retreating = Off)

	local light1_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_rhino" )
	Ability.DoAbilitySearchLight( self.squad_ai, light1_id, " vehicle" )

	local light2_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_dreadnought" )
	Ability.DoAbilitySearchLight( self.squad_ai, light2_id, " vehicle" )

	local light3_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_whirlwind" )
	Ability.DoAbilitySearchLight( self.squad_ai, light3_id, " vehicle" )

	local light4_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_predator" )
	Ability.DoAbilitySearchLight( self.squad_ai, light4_id, " vehicle" )

	local light5_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_landraider" )
	Ability.DoAbilitySearchLight( self.squad_ai, light5_id, " vehicle" )

end

	-- Call standard method
	VehicleTactic.DoAbilities(self)

end

function SpaceMarineVehicleTactic:SearchLight( squad_ai, state )

		 if self:HasAbility( "night_dummy_space_marine" ) == 1 then

	-- Check if vehicle can use searchlight
	local id = cpu_manager.stats:GetAbilityID( "marines_searchlight_rhino" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_dreadnought" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_whirlwind" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_predator" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_landraider" )
	if (not squad_ai:CanDoAbility(id)) then
		return
	end
	
	-- It's already in desired state
	if (squad_ai:IsUsingAbility(id) == state) then
		return 
	end
	
	-- Activate searchlight
	squad_ai:DoSpecialAbility(id)
end

end

See the two problems? You likely identified the first when the toggle should occur. The second one: how to allow the scripts using the AbilityIDs to work even when the NightShift Mod is NOT working. The AI should look for the presence of a certain ability "night_dummy_space_marine" in the mod's \abilities folder then, once found, pass that to the next scripts relevant to NightShift.

Is that possible or a better way?
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#6 Corsix

Corsix

    Code Monkey

  • Hosted
  • 290 posts
  • Location:Berkeley, UK
  • Projects:DoW AI, DoW Mod Studio
  •  Blue Text :)

Posted 23 March 2006 - 03:35 PM

To be honest I think you just want to open a place were demands of other mods are satisfied by us

You know thud too well :lol:
Posted Image

#7 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 23 March 2006 - 04:55 PM

Yes and No. I do not remotely expect this forum to be super busy with multitude of custom AI requests but just some unique and fascinating concepts I want to bring forth to you all.

Think of this as a fun diversion outside the normal realm of what we are used to in the game.
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#8 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 24 March 2006 - 05:52 AM

But this is completely in the realm. Ok, I made my point. Back to your problem.

Whats happening with
local light1_id = cpu_manager.stats:GetAbilityID( "marines_searchlight_rhino" )


while there is no such ability available ? Is the game crashing (bad) or is light1_id == nil (good) ?

While the second is true you can just take my code and add
		if (lights_id ~= nil and  self.squad_ai:CanDoAbility(lights_id)) then

If you really have to check for the existance of a file you can use
local file_id = io.open("filename with relative path to ability or whatever", "r")

If file_id == nil then the file does not exist.
Ugly imo.

Edited by LarkinVB, 24 March 2006 - 06:01 AM.


#9 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 24 March 2006 - 02:13 PM

Yea the problem is GetAbilityID since its expecting the ability to exist and if it doesn't the game crashes. The challenge is to check if the file exists and, if it does, pass it thru to the next sections which all have GetAbilityID. So.. the script would look like:

local light1_id = io.open("\attrib\abillities\night_dummy_space_marine", "r")
if (lights1_id ~= nil and  self.squad_ai:CanDoAbility(lights1_id)) then

And that will pass it off to the next scripts as a check?
What about the path.. is that a dynamic or static one? It has to be one that takes into account different folders when the mod is installed.
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#10 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 24 March 2006 - 03:00 PM

If you want have a clean check for the path, then you have to read out the nightshift.module file, since the mod main folder path is defined there. Then you have to add the sub path and your full path is finished. So far the theory...

#11 LarkinVB

LarkinVB

    title available

  • Members
  • 1,488 posts

Posted 24 March 2006 - 03:46 PM

Not

local light1_id = io.open("\attrib\abillities\night_dummy_space_marine", "r")
if (lights1_id ~= nil and  self.squad_ai:CanDoAbility(lights1_id)) then

but

 local light1_id = cpu_manager.stats:GetAbilityID("marines_searchlight_rhino" )
local file_id = io.open("\attrib\abillities\night_dummy_space_marine", "r")
if (file_id ~= nil and  self.squad_ai:CanDoAbility(light1_id)) then


Why do you want to add this ? It's ugly code, doesn't beleong to core and you don't want to make it part of the skirmish AI mod. If the nightshift mod wants to have lights the nightshift mod should use its own AI. Then you can be sure the ability is available.

#12 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 25 March 2006 - 06:52 PM

Still not working..

local light1_id = cpu_manager.stats:GetAbilityID("marines_searchlight_dreadnought" )
local file_id = io.open("\attrib\abilities\night_dummy_space_marine", "r")
if (file_id ~= nil and self.squad_ai:CanDoAbility(light1_id)) then
Ability.DoAbilitySearchLight( self.squad_ai, light1_id, " vehicle" )

Its not finding the io.open file or it needs the whole path? Are there wildcards I could add? I did try the whole path but it still won't pass it over.

The reason I want this working is just to see it work for the future. Call it a major experiment in AI scripting as this is the first time its been done in DoW/WA. Having the AI check the existence of a file to then pass to the next scripts even if the checked file isn't there.

Any other suggestions on above?

Btw.. is this section needed afterwards? It is used for Fleet of Foot to work.

function SpaceMarineVehicleTactic:SearchLight( squad_ai, state )

	-- Check if vehicle can use searchlight
	local id = cpu_manager.stats:GetAbilityID( "marines_searchlight_rhino" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_dreadnought" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_whirlwind" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_predator" ) or
	cpu_manager.stats:GetAbilityID( "marines_searchlight_landraider" )
	if (not squad_ai:CanDoAbility(id)) then
		return
	end
	
	-- It's already in desired state
	if (squad_ai:IsUsingAbility(id) == state) then
		return 
	end
	
	-- Activate searchlight
	squad_ai:DoSpecialAbility(id)
end

Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#13 Corsix

Corsix

    Code Monkey

  • Hosted
  • 290 posts
  • Location:Berkeley, UK
  • Projects:DoW AI, DoW Mod Studio
  •  Blue Text :)

Posted 26 March 2006 - 02:38 PM

You want to change the filename from "\attrib\abilities\night_dummy_space_marine" to "mod_folder\\data\\attrib\\abilities\\night_dummy_space_marine"
Posted Image

#14 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 27 March 2006 - 01:13 AM

Damn!

It almost worked.. problem however is the same..

io.open and GetAbilityID do the same thing: when used the item they're referencing MUST exist in the game or else they will crash back to desktop. Ugh!

I tried:
		  local file_id = io.open("Night_Shift\\data\\attrib\\abilities\\night_dummy_space_marine.rgd", "r")
		  if (file_id ~= nil) then
And it passes over to NightShift fine now BUT if the NightShift mod is NOT activated then the game will crash. Ughhhh! So back to square one.

There has to be a script that can check for the existence of a file or whatever WITHOUT having to have that file active (thus causing a crash when its there). The script must adapt to if the file is either there or not.
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#15 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 27 March 2006 - 03:13 AM

Okie.. I think I know why this is gonna be difficult..

The script must check and do 3 critical things:
1) Must work when the Night_Shift mod is present but NOT active
2) Must work when the Night_Shift mod is NOT present and NOT active
3) Must work when the Night_Shift mod is present and active

The problem arises when the mod is present but NOT active. How does the script:

local file_id = io.open("Night_Shift\\data\\attrib\\abilities\\night_dummy_space_marine.rgd", "r")

.. know when its NOT being used?

Before I could use the script:

if self.player_stats:GetPlayerRaceName() == "<faction name>_race" then

to check for the existence of a third-party faction and thus it was easy to ensure no conflicts would occur.

Now I'm checking for a mod that is integrated with the existing vanilla factions so to get all 3 above criteria met is hell. Really busting my balls trying to figure out the logic on this. :D
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#16 thudo

thudo

    Wacko AI Guy!

  • Division Leaders
  • 12,166 posts
  • Location:Lemonville North, Canada
  • Projects:DoW AI Scripting Project
  • Division:DoW
  • Job:Division Leader

Posted 27 March 2006 - 03:36 AM

Final update (before I throw the towel in)..

Okay.. Is there a script that can check to see if the squad has the ability in the first place:

I have this:
function Tactic:HasAbility( ability_id )

	-- Get Ability ID
	local iAbilityID = cpu_manager.stats:GetAbilityID( ability_id )

		if (iAbilityID == ability_id ) then
			return true
		end

	return false
end

use with this:

if self.squad_ai:HasAbility( "marines_searchlight_dreadnought" ) then

So it will add an extra check to see if the unit indeed has that ability stored in it during gametime (in other words, when the NightShift mod is NOT running, the Dreadnought squad will obviously not have that ability).

Thanks all for hanging in!
Advanced Skirmish AI Team Lead for the coolest Warhammer40k PC RTS out there:

Dawn of War Advanced AI Headquarters

Latest DoW Advanced AI Download!

#17 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 27 March 2006 - 02:29 PM

1) Must work when the Night_Shift mod is present but NOT active

I think this the main problem. The other cases should work with your code. I'm not sure where Relic stores the information of the current active mod. Maybe it's just an entry in an *.ini file. Not sure...

if self.squad_ai:HasAbility( "marines_searchlight_dreadnought" ) then

If you want to call Tactic:HasAbility(...), then you have do use it like that:

if self.squad_ai:GetTactic():HasAbility( "marines_searchlight_dreadnought" ) then


#18 Corsix

Corsix

    Code Monkey

  • Hosted
  • 290 posts
  • Location:Berkeley, UK
  • Projects:DoW AI, DoW Mod Studio
  •  Blue Text :)

Posted 27 March 2006 - 03:33 PM

BUT if the NightShift mod is NOT activated then the game will crash

Ahh yeah, you need to wrap the io.open in a pcall:
local file_id = nil
file_id = pcall(io.open, "Night_Shift\\data\\attrib\\abilities\\night_dummy_space_marine.rgd", "r"))
		  if (file_id ~= nil) then

As for finding the active mod:
function Util_GetIniSetting(sFile, sVal, sDef)
	local ini = nil
	ini = io.open(sFile, "r")
	if(ini ~= nil) then
		for line in ini:lines() do
			for k, v in string.gfind(line, "(%w+)=(%w+)") do
				if(k == sVal) then
					return v
				end
			end
		end
	end
	return sDef
end

function GetActiveDowMod()
	return Util_GetIniSetting("Local.ini", "currentmod", "w40k")
end

function GetActiveWxpMod()
	return Util_GetIniSetting("Local.ini", "currentmodwa", "wxp")
end
I've also put together two other helper functions: ModIsPresent and ModIsActive. Both take the module file name (eg. "w40k", "tau_mod", "my_mod" etc.) and a true/false value specifying wether its a WA mod or not (eg. set to true if you're using W40kWA.exe for the mod, set to false if you're using W40k.exe)
function Util_GetIniSetting(sFile, sVal, sDef)
	local ini = nil
	ini = io.open(sFile, "r")
	if(ini ~= nil) then
		for line in ini:lines() do
			for k, v in string.gfind(line, "(%w+)=(%w+)") do
				if(k == sVal) then
					return v
				end
			end
		end
	end
	return sDef
end

function GetActiveDowMod()
	return Util_GetIniSetting("Local.ini", "currentmod", "w40k")
end

function GetActiveWxpMod()
	return Util_GetIniSetting("Local.ini", "currentmodwa", "wxp")
end

function ModIsActive(module_file, iswa)
	if(iswa == true) then
		if(string.lower(GetActiveWxpMod()) == string.lower(module_file)) then
			return true
		else
			return false
		end
	else
		if(string.lower(GetActiveDowMod()) == string.lower(module_file)) then
			return true
		else
			return false
		end
	end
end

function ModIsPresent(module_file, iswa)
	local file_id = nil
	file_id = pcall(io.open, module_file .. ".module", "r"))
	if (file_id ~= nil) then
		file_id:close()
		return true
	else
		return false
	end
end

Edited by Corsix, 27 March 2006 - 03:36 PM.

Posted Image

#19 ArkhanTheBlack

ArkhanTheBlack

    title available

  • Members
  • 814 posts

Posted 27 March 2006 - 06:16 PM

Wow! I think Thudo will highly appreciate this code. ;)

A question Corsix:

You are using pcall to avoid a crash. (Reminds me of on error goto in good old VB...)
Do you thing it's possible to do the same with the buggy terrainanalyzer functions GetPathingDistance() and HasThreatOnPath()? I personally doubt it since it's not an original LUA function, but I'm not sure.

#20 Corsix

Corsix

    Code Monkey

  • Hosted
  • 290 posts
  • Location:Berkeley, UK
  • Projects:DoW AI, DoW Mod Studio
  •  Blue Text :)

Posted 27 March 2006 - 06:50 PM

If a C++ function bound to lua via the standard lua api wants to throw an error it can:
a. throw a C++ exception
b. return 0 or NULL
c. call lua_error()
In this situation, if the function uses method 'a' then pcall will not help, if it uses method 'b' then you can check the return value and if it uses method 'c' then pcall will surpress the error. Now, if a C++ function is bound to lua via luabind, which is what DoW uses, then method 'a' will turn int method 'c' and therefore be surpressed by pcall.

Unfortunatley, if the error is more serious, eg. stack corruption, invalid memory access, etc. then the MSVC runtime will detect that, DoW will CTD and the error reporting thing will appear.

So in conclusion, as long as the bug does not bring up the error reporting thingy then pcall will help.
Posted Image




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users