Third Resource Behavior Example

Third Resource Behavior Example

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Third Resource Behavior Example

Post by Argh »

[EDIT]Now handles Cloak costs as well as weapons and fixed costs[/EDIT]

Here's the script I'm using for handling Power in P.U.R.E. in a non-standard way, using Unit customParams. I figured this would be handy for people wanting to use third, fourth, etc. resources but who are unsure how to go about this kind of bookkeeping.

Please note that this particular implementation doesn't include handling of storage (I am doing away with storage in P.U.R.E.), but I'm sure that after reading through this, you can figure that out for yourselves :-)

The resources are globalized here so that they can be picked up as SYNCED values for the P.U.R.E. UI.

Only issue with it is an oddity: when COB performs the check for weapons, it does it *twice* for some odd reason, even if it's supposed to be locked out by a variable state. I haven't had time to poke at that yet.

Code: Select all

function gadget:GetInfo()
	return 
	{
		name = "P.U.R.E. Power",
		desc = "Power Economics Handler.",
		author = "Argh",
		date = "March 2nd, 2010",
		license = "(C) Wolfe Games, GPL v. 2",
		layer = 10000,
		enabled = true
	}
end

GG.Power = {}
GG.PowerCost = {}
GG.PowerMake = {}
GG.PowerCostDisplay = {}
gadgetHandler:RegisterGlobal("Global_Power", GG.Power)
gadgetHandler:RegisterGlobal("Global_PowerCost", GG.PowerCost)
gadgetHandler:RegisterGlobal("Global_PowerCostDisplay", GG.PowerCostDisplay)
gadgetHandler:RegisterGlobal("Global_PowerMake", GG.PowerMake)

local UnitPowerCost = {}
local UnitCloakCost = {}
local UnitPowerMake = {}

if (gadgetHandler:IsSyncedCode()) then
------------------------------------------------------------------------------------------------------------Facilitates COB/Lua-animation communication
function CheckPower(u, ud, team,cost)
	if GG.Power[team] > cost then
		GG.Power[team] = GG.Power[team] - cost
		GG.PowerCostDisplay[team] = GG.PowerCostDisplay[team] + cost
		return u, ud, team, 1		
	else 
		return u, ud, team, 0
	end
end
gadgetHandler:RegisterGlobal("CheckPower", CheckPower)

------------------------------------------------------------------------------------------------------------Initializes variables and preps the cost / make tables
function gadget:Initialize()
	local temp = Spring.GetTeamList()
	for _,Team in ipairs(temp) do
		GG.Power[Team] = 0
		GG.PowerCost[Team] = 0
		GG.PowerMake[Team] = 0
		GG.PowerCostDisplay[Team] = 0
	end

	--Iterate through the UnitDefs, find out which Units make or cost Power to operate
	for ud,_ in pairs(UnitDefs) do
		if UnitDefs[ud].customParams.cloak_cost ~= nil then
			table.insert(UnitCloakCost,ud,UnitDefs[ud].customParams.cloak_cost)
		end
		if UnitDefs[ud].customParams.power_cost ~= nil then
			table.insert(UnitPowerCost,ud,UnitDefs[ud].customParams.power_cost)
		end
		if UnitDefs[ud].customParams.power_make ~= nil then
			table.insert(UnitPowerMake,ud,UnitDefs[ud].customParams.power_make)
		end
	end
end
------------------------------------------------------------------------------------------------------------Enters the Units into the ledger
function gadget:UnitFinished(unitID, unitDefID, teamID)
	if UnitPowerCost[unitDefID] then
		GG.PowerCost[teamID] = GG.PowerCost[teamID] + UnitPowerCost[unitDefID]
	end
	if UnitPowerMake[unitDefID] then
		GG.PowerMake[teamID] = GG.PowerCost[teamID] + UnitPowerMake[unitDefID]
	end
end
------------------------------------------------------------------------------------------------------------Handles transferred / captured Units
function gadget:UnitGiven(unitID, unitDefID, teamID, oldTeam)
	if UnitPowerCost[unitDefID] then
		GG.PowerCost[teamID] = GG.PowerCost[teamID] + UnitPowerCost[unitDefID]
		GG.PowerCost[oldTeam] = GG.PowerCost[oldTeam] - UnitPowerCost[unitDefID]
	end
	if UnitPowerMake[unitDefID] then
		GG.PowerMake[teamID] = GG.PowerMake[teamID] + UnitPowerMake[unitDefID]
		GG.PowerMake[oldTeam] = GG.PowerMake[oldTeam] - UnitPowerMake[unitDefID]
	end
end

------------------------------------------------------------------------------------------------------------Cloaking
function gadget:UnitCloaked(unitID, unitDefID, teamID)
	if UnitCloakCost[unitDefID] then
		GG.PowerCost[teamID] = GG.PowerCost[teamID] + UnitCloakCost[unitDefID]
	end
end

function gadget:UnitDecloaked(unitID, unitDefID, teamID)
	if UnitCloakCost[unitDefID] then
		GG.PowerCost[teamID] = GG.PowerCost[teamID] - UnitCloakCost[unitDefID]
	end
end

function gadget:AllowCommand(unitID, unitDefID, unitTeam, cmdID, cmdParams, cmdOptions, cmdTag, synced)
	if cmdID == CMD.CLOAK and cmdParams[1] == 1 and UnitCloakCost[unitDefID] then
		if GG.Power[unitTeam] - UnitCloakCost[unitDefID] < 0 then
			return false
		else
			return true
		end
	else
		return true
	end
end
------------------------------------------------------------------------------------------------------------Removes dead Units from ledger
function gadget:UnitDestroyed(unitID, unitDefID, teamID)
	if UnitPowerCost[unitDefID] then
		GG.PowerCost[teamID] = GG.PowerCost[teamID] - UnitPowerCost[unitDefID]
	end
	if UnitPowerMake[unitDefID] then
		GG.PowerMake[teamID] = GG.PowerMake[teamID] - UnitPowerMake[unitDefID]
	end
end
------------------------------------------------------------------------------------------------------------Updates current state
function gadget:GameFrame(f)
	local teamList = Spring.GetTeamList()
	if f % 32 < 0.01 then

	for _,Team in ipairs(teamList) do
		GG.Power[Team] = math.max((GG.Power[Team] + GG.PowerMake[Team] - GG.PowerCost[Team]),0)
		if GG.Power[Team] == 0 then
			for _,unitID in ipairs(Spring.GetTeamUnits(Team)) do
				if Spring.GetUnitIsCloaked(unitID) == true then
					--Spring.Echo("shutting down cloak")
					Spring.GiveOrderToUnit(unitID,CMD.CLOAK,{0},0)
				end
			end
		end
		GG.PowerCostDisplay[Team] = 0
		--Spring.Echo("GG.Power for "..Team.." is "..GG.Power[Team])
	end
	end
end

end
Example COB script (for weapons which use Power)

Code: Select all

#define POWER_COST 100
lua_CheckPower(arg) { return (0); }
AimWeapon1(heading, pitch)
{
	//do aiming stuff as normal

	call-script lua_CheckPower(POWER_COST);
	return(GET LUA4);
}
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Third Resource Behavior Example

Post by bobthedinosaur »

What about a factories that may use the resources? I'm guessing a while function with 1000 sleep and the same cost for the defined resource per second costs?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Third Resource Behavior Example

Post by Argh »

No, you just need a AllowBuildStep() handling that situation. Here's an example:

Code: Select all

function gadget:AllowUnitBuildStep(builderID, builderTeam, u, ud, part)
	if UnitPowerCost[ud] then
		local powerLeft = GG.Power[builderTeam] - (UnitPowerCost[ud] * part)
		if powerLeft > 0 then
			GG.Power[builderTeam] = powerLeft
			GG.PowerCostDisplay[builderTeam] = GG.PowerCostDisplay[builderTeam] + (UnitPowerCost[ud] * part)
			return true
		else
			return false
		end
	end
end
If it returns false, then the build-step is not allowed. I do some slight-of-hand in this code, in terms of displaying draw, but otherwise it's just basic math. Works just fine in Factories; it could very easily be adjusted for a pay-before-start model like StarCraft, AoE, etc. as well.
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Third Resource Behavior Example

Post by bobthedinosaur »

can you post a pay before purchase example, and a resource drain such as radar, mmaker, or other on/off resource drains?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Third Resource Behavior Example

Post by Argh »

I haven't done anything about ON/OFF, and I don't plan to support that feature.

It could be handled via the GameFrame() check- simply send them commands to turn on/off at that point. However, there would be some complications. The engine wouldn't know the difference between manually-set user-state on-off, so additional code would have to be added to handle these special cases, or a priority system would have to be developed. I have no plans to do so at this time.

Pay-at-once can be very straightforward:

Code: Select all

function gadget:AllowUnitBuildStep(builderID, builderTeam, u, ud, part)
	if UnitPowerCost[ud] and paidFor[u] ~= nil then
		local powerLeft = GG.Power[builderTeam] - UnitPowerCost[ud]
		if powerLeft > 0 then
			GG.Power[builderTeam] = powerLeft
			GG.PowerCostDisplay[builderTeam] = GG.PowerCostDisplay[builderTeam] + UnitPowerCost[ud]
			paidFor[u] = 1
			return true
		else
			return false
		end
	else
		return true
	end
end
All I've done here is change the amount required to be paid on the first build step- until you have enough Power in the bank, you cannot build the Unit. Once you've paid, it's entered into the paidFor table, so that the cost will not recur. Depending on the type of specific implementation you want, there are other variants, ofc, but that's one of the simpler ones.
Post Reply

Return to “Lua Scripts”