Ever wished to script fun stuff with ogres' charging attacks, but had to resort to improbable hacks to make it happen? Ever just wished for an "onCharge" hook?
Enter the Ogre Tracker! (tu-dum).
A simple to use tracking system for ogres which allows you to add onCharge(self, startingX, startingY) and onChargeEnd(self) hooks to your monster.
1. put that script in a script entity named ogreTracker:
SpoilerShow
Code: Select all
--[[
OGRE TRACKING SYSTEM
Version: 0.9
Scripting by Diarmuid
]]
debugMessages = false;
ogres = {}
function startTracking(id)
if (ogres[id]) then return; end
local ogreEntity = findEntity(id);
if not(ogreEntity) then return; end
ogres[id] = {};
local ogre = ogres[id];
ogre.id = id;
ogre.moveDir = -1;
ogre.chargeDir = -1;
ogre.x = ogreEntity.x;
ogre.y = ogreEntity.y;
ogre.stopCtr = 0;
if fw then
fw.setHook(id..".ogreTracker.onMove",
function(monster, direction)
if ogreTracker and ogreTracker.ogres[monster.id] then
ogreTracker.ogres[monster.id].moveDir = direction;
end
return true;
end
)
end
ogre.update = function(self)
local ogreEntity = findEntity(self.id);
if not(ogreEntity) then
self:stopTracking();
return;
end
local level, x, y = ogreEntity.level, ogreEntity.x, ogreEntity.y;
if x ~= self.x or y ~= self.y then
if self.moveDir ~= -1 then
self.moveDir = -1;
self.x = x;
self.y = y;
else
if y < self.y then self.chargeDir = 0; end
if x > self.x then self.chargeDir = 1; end
if y > self.y then self.chargeDir = 2; end
if x < self.x then self.chargeDir = 3; end
if not(self.charging) then
if debugMessages then
print("OGRE TRACKER: "..self.id.." started charging at ", level, self.x, self.y, "facing", self.chargeDir);
end
if self.onCharge then
self.onCharge(ogreEntity, self.x, self.y);
end
end
self.x = x;
self.y = y;
self.charging = true;
end
elseif self.chargeDir ~= -1 then
if self.stopCtr < 4 then
self.stopCtr = self.stopCtr + 1;
else
if debugMessages then
print("OGRE TRACKER: "..self.id.." ended its charge at ", level, x, y, "facing", self.chargeDir);
end
self.moveDir = -1;
self.x = x;
self.y = y;
if self.onChargeEnd then
self.onChargeEnd(ogreEntity);
end
self.chargeDir = -1;
self.stopCtr = 0;
self.charging = false;
end
end
end;
ogre.stopTracking = function(self)
if debugMessages then
print("OGRE TRACKER: stopped tracking "..self.id);
end
if fw then fw.removeHook(self.id..".ogreTracker.onMove"); end
ogreTracker.ogres[self.id] = nil;
end;
if debugMessages then
print("OGRE TRACKER: started tracking "..id);
end
return ogre;
end
function stopTracking(id)
if ogres[id] then ogres[id]:stopTracking(); end
end
function addHook(id, hookName, funct)
local ogre = ogres[id];
if not(ogre) then
print("OGRE TRACKER: warning, trying to add hook to "..id..", not registered for tracking");
return;
end
if hookName == "onCharge" then
ogre.onCharge = funct;
elseif hookName == "onChargeEnd" then
ogre.onChargeEnd = funct;
end
end
function update()
for _, ogre in pairs(ogres) do
ogre:update();
end
end
3. If your mod uses the LoG framework, nothing else is required for setup. If you don't you need to manually add this to the onMove hook of the monsters you wish to track:
SpoilerShow
Code: Select all
onMove = function(monster, direction)
if ogreTracker and ogreTracker.ogres[monster.id] then
ogreTracker.ogres[monster.id].moveDir = direction;
end
return true;
end
USAGE:
First you need to register the monster in the tracker by calling
Code: Select all
ogreTracker.startTracking(id)Code: Select all
ogreTracker.addHook(id, "onCharge", function(self, startingX, startingY)
--Put your code here
end)
ogreTracker.addHook(id, "onChargeEnd", function(self)
--Put your code here
end)
Code: Select all
ogreTracker.stopTracking(id)Also, don't worry, the system will stop tracking automatically and cleanUp data if the monster dies or is destroyed.
a debugMessages variable at the top allows you to get some info on what hooks are called.
IMPORTANT NOTE: The system detects the charge AFTER the monster already started it and is one square away. That's why onCharge returns a startingX and a startingY parameter so that you can know the initial position.This means you cannot use this system to "prevent" the monster from charging on certain conditions, but you can always stop it after a 1 tile charge by spawning a blocker on the next square, if you wish.