-- Player Unit Actions -- -- Author: Dearthenon (Daniel Carruth) -- Revisions -- 11/15/08: Creation (DWC) -- Properties Define Properties() selected_object_id = 0 -- selected_object_label = 0 -- command_state = "default" selected_unit_index = 1 -- Team Members -- name sprite template team = { {"Warrior", '0:687', '0:4'}, {"Knight", '0:688', '0:5'}, {"Sorcerer", '0:689', '0:6'} } -- User Interace teamPanel = 0 unitPanel = 0 script_description = 'Player Unit Actions' script_long_description = 'Player Controls Units' end Define Commands() -- MakeCommand(name, description, [arg-name:arg-type, ...]) -- MakeInput(input-description, input-code, input-event, input-modifier, command-string) -- ** MAIN SCREEN COMMANDS ** -- handle click on terrain MakeCommand("handle_terrain", "request move", "x:float", "y:float", "z:float") MakeInput('Click on terrain.', 'mouse-terrain', 'click', 'none', 'handle_terrain') -- handle click on an object MakeCommand("pick", "pick an object", "target:object") MakeInput('pick','mouse-object', 'click', 'none', 'pick') -- test -- various test functions used to test functionality MakeCommand("test", "test") MakeInput('test', 'a', 'down', 'none', 'test') MakeCommand("test2", "test2") MakeInput('test2', 's', 'down', 'none', 'test2') MakeCommand("test3", "test3", "val:int") -- ** TEAM PANEL COMMANDS ** -- select unit MakeCommand("selectUnit", "select the specified unit", "val:int") -- end turn MakeCommand("endTurn", "endTurn") -- ** UNIT PANEL COMMANDS ** -- hold unit MakeCommand("holdUnit", "Orders the selected unit to hold") MakeInput('order unit to hold until next turn', 'h', 'down', 'none', 'holdUnit') -- shift selection to next unit MakeCommand("nextUnit", "Selects the next unit with remaining AP") MakeInput('select next unit with available AP', 'n', 'down', 'none', 'nextUnit') -- display inventory MakeCommand("showUnitInventory", "Displays the unit inventory window") MakeInput('display inventory screen for current unit', 'i', 'down', 'none', 'showUnitInventory') -- display status MakeCommand("showUnitStatus", "Displays the unit stats window") MakeInput('display status screen for current unit', 's', 'down', 'none', 'showUnitStatus') -- hand MakeCommand("useHandItem", "Activates item in left hand", "hand:string") -- belt slots MakeCommand("useBeltSlot", "Activates item in belt slot", "slotNumber:int") end -- **** COMMANDS **** -- ** MAIN SCREEN COMMANDS ** -- pick -- Click on an object - no SHFT, CTRL, ALT modifiers Command pick(target) -- select unit objects on click if (target.owner == self.id) then selectUnit(self, target) end end -- handle_terrain -- Click on the terrain - no SHFT, CTRL, ALT modifiers Command handle_terrain(x, y, z) -- if selected object is one of our units, order it to move if (GetObjectById(self.selected_object_id).owner == self.id) then -- move the player with the unit self.speed = 2 PathToLocation(self, round(x), round(y)) -- request unit to move SendTo(GetObjectById(self.selected_object_id), "requestMove", 0, x, y) end end -- Test -- Reusable commands for testing new script(s) Command test() createTeamUI(self) createUnitUI(self) end Command test2() destroyUI(self) end Command test3(val) if val == 0 then AlertToUser(self, 1500, "HOLD") elseif val == 2 then AlertToUser(self, 1500, "NEXT UNIT") elseif val == 3 then AlertToUser(self, 1500, "STATS") else AlertToUser(self, 1500, "INVENTORY") end --selectUnit(self, GetObjectById(self.team[val].id)) --destroyUnits(self) end -- ** TEAM PANEL COMMANDS ** -- selectUnit -- selects a specified unit Command selectUnit(val) selectUnit(self, GetObjectById(self.team[val].id)) end -- endTurn -- ends the user's current turn Command endTurn() SendTo(self, "startTurn", 0) end -- ** UNIT PANEL COMMANDS ** -- holdUnit -- orders the current unit to hold until the next turn -- effectively it makes the nextUnit command ignore it until the next turn Command holdUnit() AlertToUser(self, 1500, "Hold Unit!") SendTo(GetObjectById(self.team[self.selected_unit_index].id), "hold", 0) end -- nextUnit -- selects the next available unit with AP Command nextUnit() AlertToUser(self, 1500, "Next Unit!") -- local var for unit storage local unit = 0 -- store where we start the search local startIndex = self.selected_unit_index -- increment the index and create a local copy local selectIndex = self.selected_unit_index + 1 if selectIndex > #(self.team) then selectIndex = 1 end -- loop thru the team table until we return to the start index while selectIndex ~= startIndex do --Debug("%d - %d", selectIndex, startIndex) -- if the unit has available AP and is not on hold, select the unit unit = GetObjectById(self.team[selectIndex].id) if (unit.actionPoints > 0 and unit.state ~= "hold") then selectUnit(self, GetObjectById(self.team[selectIndex].id)) return end selectIndex = selectIndex + 1 -- set the index to start of team table if we reach the end of the table if selectIndex > #(self.team) then --Debug("Out of range") selectIndex = 1 end end -- check the current unit unit = GetObjectById(self.team[startIndex].id) if (unit.actionPoints > 0 and unit.state ~= "hold") then AlertToUser(self, 1500, "Other Units Out of Action Points!") else AlertToUser(self, 1500, "All Units Out of Action Points!") end end -- showUnitInventory -- displays the inventory UI for the selected unit Command showUnitInventory() AlertToUser(self, 1500, "Inventory!") end -- showUnitStatus -- displays the status UI for the selected unit Command showUnitStatus() AlertToUser(self, 1500, "Stats!") end -- useHandItem -- use item in hand -- Args: -- hand - which hand Command useHandItem(hand) AlertToUser(self, "%s Hand!", hand) end -- useBeltSlot -- belt slots -- Args: -- slotNumber - which belt slot to activate Command useBeltSlot(slotNumber) AlertToUser(self, "Belt Slot %d!", slotNumber) end -- TRIGGERS -- attach -- System Trigger: sent when script is attached Trigger attach() -- set the user sprite to blank self.spriteId = '12071:448' end -- enter -- System Trigger: sent when user/object enters place Trigger enter(placeId) -- cleanup the units if they exist destroyUnits(self) -- create the user's units createUnits(self) -- setup the team panel createTeamUI(self) -- setup the unit panel createUnitUI(self) -- select one of the units selectUnit(self, GetObjectById(self.team[self.selected_unit_index].id)) end -- left -- System Trigger: sent when user/object leaves place Trigger left(placeId, logoutFlag) -- cleanup user units destroyUnits(self) -- cleanup user ui destroyUI(self) end -- startTurn Trigger startTurn() AlertToUser(self, 1500, "Your Turn!") for k, unit in pairs(self.team) do -- Debug("unit: %d %s", k, unit.name) SendTo(GetObjectById(unit.id), "resetUnit", 0) end end -- attachSelected -- Custom Trigger: sent from an object that has been selected -- sets the selected_object_id to the object's id -- TODO: no longer in use? Trigger attachSelected(object) self.selected_object_id = object.id end -- FUNCTIONS -- selectUnit -- selects the specified unit -- Args: -- self - user object -- target - unit object to select function selectUnit(self, target) -- Move the user to the selected unit MoveObject(self, target.x, target.y, 1, 1) -- Send message to target object to handle selection SendTo(target, "selectUnit", 0, self) -- Send message to previously selected object to handle deselection if self.selected_object_id ~= 0 then SendTo(GetObjectById(self.selected_object_id), "unselectUnit", 0, self) end -- store id of selected object self.selected_object_id = target.id self.selected_unit_index = getUnitIndexById(self, target.id) -- TODO: Update user interface panels end -- round -- rounds num -- Args: -- num - number to round -- idp - decimal places, 0 - whole number function round(num, idp) local mult = 10^(idp or 0) return math.floor(num * mult + 0.5) / mult end -- destroyUI -- cleans up the user interfaces -- Args: -- user - user object function destroyUI(user) -- clean up the team panel if(user.teamPanel ~= 0) then UiDelete(user.teamPanel) user.teamPanel = 0 end -- clean up the unit panel if(user.unitPanel ~= 0) then UiDelete(user.unitPanel) user.unitPanel = 0 end end -- createTeamUI -- creates the team panel interface -- Args: -- user - user object function createTeamUI(user) -- if it already exists for some reason, clear the old panel if (user.teamPanel ~= 0) then UiDelete(user.teamPanel) user.teamPanel = 0 end -- Debug("Creating Team UI") -- create the root element of the panel user.teamPanel = UiElement(0, "teamControlPanel", 0, 0) -- create the component elements createTeamPanel(user) -- attach the panel to the user -- Debug("Attaching window %d", user.teamPanel) UiAttachUser(user,user.teamPanel) end -- createTeamPanel -- creates the team panel components -- Args: -- user - user object function createTeamPanel(user) -- local vars for creation local count = 0 local button = 0 local y = 0 local rect = 0 local unitObject = 0 -- create the background rect of the panel local panel = UiRect(user.teamPanel, "teamPanel", 0, 0, 50, 250) UiColor(panel, 180, 128, 0, 1) -- loop over the units in the team and create unit data panels/buttons for k, unit in pairs(user.team) do -- calculate the y location of the button y = 54*count + 9 -- create the outer rectangle rect = UiRect(panel, "rect", 8, y-1, 34, 34) UiColor(rect, 0, 0, 0, 1) -- create the inner rectangle rect = UiRect(panel, "rect", 9, y, 32, 32) UiColor(rect, 180, 148, 0, 1) -- create the button using the sprite button = UiImageButton(panel, "unit"..k, 9, y, 32, 32, unit[2], unit[2], unit[2], 'selectUnit '..k) -- create stats rect unitObject = GetObjectById(unit.id) -- health rect = UiRect(panel, "rect", 8, y+35, 34, 4) UiColor(rect, 0, 0, 0, 1) unitObject.healthRect = UiRect(panel, "HP", 9, y+36, 32, 2) UiColor(unitObject.healthRect, 255, 0, 0, 1) -- energy rect = UiRect(panel, "rect", 8, y+40, 34, 4) UiColor(rect, 0, 0, 0, 1) unitObject.healthRect = UiRect(panel, "EP", 9, y+41, 32, 2) UiColor(unitObject.healthRect, 0, 0, 255, 1) -- AP rect = UiRect(panel, "rect", 8, y+45, 34, 4) UiColor(rect, 0, 0, 0, 1) unitObject.apRect = UiRect(panel, "AP", 9, y+46, 32, 2) UiColor(unitObject.apRect, 0, 255, 0, 1) count = count + 1 end -- create the end turn button button = UiImageButton(panel, "endturn", 9, 216, 32, 32, '12071:430', '12071:430', '12071:430', 'endTurn') -- add a tooltip to the button - TODO: NOT WORKING -- UiTooltip(button, "End Turn") end -- createUnitUI -- creates the unit interface -- Args: -- user - user object function createUnitUI(user) -- be sure the unit UI doesn't already exist if (user.unitPanel ~= 0) then UiDelete(user.unitPanel) user.unitPanel = 0 end -- create the unit UI -- Debug("Creating Unit UI") -- Create a window to hold the unit controls -- currently using default window style user.unitPanel = UiWindow(0, "unitControlWindow", 100, 340, 344, 118, '13197:3') -- allow users to drag the window UiCapability(user.unitPanel, "drag") -- create the interior of the panel createUnitPanel(user) -- attach the window to the user -- Debug("Attaching window %d", user.unitPanel) UiAttachUser(user,user.unitPanel) end -- createUnitPanel -- creates the unit panel components -- Args: -- user - user object function createUnitPanel(user) -- some local vars for handling creation of the UI local x = 64 local y = 62 local width = 48 local height = 48 local paddingx = 8 local rect = 0 -- create two rows of 4 button outlines -- first row: 48x24 -- second row: 48x48 for i=0,3,1 do rect = UiRect(user.unitPanel, "rect", x+(i*(width+paddingx)), 30, width, 24) UiColor(rect, 0, 0, 0, 1) rect = UiRect(user.unitPanel, "rect", x+(i*(width+paddingx)) + 1, 31, width-2, 22) UiColor(rect, 255, 200, 0, 1) rect = UiRect(user.unitPanel, "rect", x+(i*(width+paddingx)), y, width, height) UiColor(rect, 0, 0, 0, 1) rect = UiRect(user.unitPanel, "rect", x+(i*(width+paddingx)) + 1, y+1, width-2, height-2) UiColor(rect, 255, 200, 0, 1) end -- create left hand area rect = UiRect(user.unitPanel, "rect", 8, 30, width, 80) UiColor(rect, 0, 0, 0, 1) rect = UiRect(user.unitPanel, "rect", 9, 31, width-2, 78) UiColor(rect, 255, 200, 0, 1) -- create right hand area rect = UiRect(user.unitPanel, "rect", x+(4*(width+paddingx)), 30, width, 80) UiColor(rect, 0, 0, 0, 1) rect = UiRect(user.unitPanel, "rect", x+(4*(width+paddingx))+1, 31, width-2, 78) UiColor(rect, 255, 200, 0, 1) -- create top row of buttons with unit commands UiImageButton(user.unitPanel, "holdButton", 64, 30, 48, 24, '0:693', '0:693', '0:693', "holdUnit") UiImageButton(user.unitPanel, "nextButton", 120, 30, 48, 24, '0:695', '0:695', '0:695', "nextUnit") UiImageButton(user.unitPanel, "invButton", 176, 30, 48, 24, '0:694', '0:694', '0:694', "showUnitInventory") UiImageButton(user.unitPanel, "statsButton", 232, 30, 48, 24, '0:696', '0:696', '0:696', "showUnitStatus") -- create left hand and right hand buttons -- create belt-slot buttons end -- createUnits -- creates the objects representing the user's units -- Args: -- user - user object function createUnits(user) local object = 0 -- loop over the team units and create them for k, unit in pairs(user.team) do unit.name = unit[1] -- map value to a name key unit.sprite = unit[2] -- map value to sprite key -- create the object from unit data, place near user's location object = CreateObjectById(unit[3], user.x, user.y+k, 0, 0) -- set unit id to the created object's id unit.id = object.id -- set the object's owner to the user's id object.owner = user.id end end -- destroyUnits -- destroys the objects representing the user's units -- Args: -- user - user object function destroyUnits(user) -- loop over the team units and remove them for k, unit in pairs(user.team) do -- check that the units exist at all if (unit.id) then -- Debug("Destroying %s", unit.name) DestroyObject(GetObjectById(unit.id)) end end -- clear the selection user.selected_object_id = 0 end function getUnitIndexById(user, id) -- loop over the team units for k, unit in pairs(user.team) do if (unit.id == id) then --Debug("Found index: %d", k) return k end end Debug("Unit (Id: %d) not found in team list", id) return nil end