[Moeng-cvs] CaveAdventure/data/scripts Player.lua,NONE,1.1 Torch.lua,NONE,1.1 Turtle.lua,NONE,1.1 Vi
Status: Alpha
Brought to you by:
b_lindeijer
From: <b_l...@us...> - 2004-01-13 19:20:12
|
Update of /cvsroot/moeng/CaveAdventure/data/scripts In directory sc8-pr-cvs1:/tmp/cvs-serv28751 Modified Files: Action.lua Pawn.lua Added Files: Player.lua Torch.lua Turtle.lua Viewport.lua Log Message: More scripts. --- NEW FILE: Player.lua --- -- -- The player character is defined here. -- By Bjorn Lindeijer import("Character.lua") import("AnimationFunctions.lua") -- (Player) character states CHR_ATTACK = 1 CHR_HIT = 2 CHR_READY = 3 CHR_DEAD = 4 Player = Character:subclass { name = "Player"; init = function(self) self:derive_attributes() Character.init(self) end; derive_attributes = function(self) -- Derived attributes self.maxHealth = 15 + 2*self.endurance self.speed = 4/95 * self.agility + 53/19 -- Player speed in tiles/second self.charge_time = (-40/95 * self.agility + 60 + 40/19) self.attack_speed = self.charge_time/2 -- Hack to play faster self.speed = self.speed * 1.4 --self.attack_speed = self.attack_speed * 0.5 --self.charge_time = self.charge_time * 0.5 --self.maxHealth = self.maxHealth * 100 end; attack = function(self) if (self.state == CHR_HIT) then return elseif (self.state == CHR_READY and self.walking == 0 and self.charging == 0) then self.state = CHR_ATTACK -- See if there is a monster at the attacked location local ax, ay = self.x, self.y if (self.dir == DIR_LEFT) then ax = ax - 1 end if (self.dir == DIR_RIGHT) then ax = ax + 1 end if (self.dir == DIR_UP) then ay = ay - 1 end if (self.dir == DIR_DOWN) then ay = ay + 1 end local attacked_objs = m_get_objects_at(ax, ay, self.map) for index, object in attacked_objs do if (object:instanceOf(Actor)) then local damage = (self.attack_min_dam + math.random(self.attack_max_dam - self.attack_min_dam))*(self.strength/95 + 18/19) object:takeDamage(damage, self) end end ActionController:addSequence{ ActionExModeOn(), ActionSetState(self, CHR_ATTACK), ActionPlaySample("bbsfx_hit1.wav"), ActionWait(self.attack_speed), ActionSetState(self, CHR_READY), ActionSetVariable(self, "charging", self.charge_time), ActionExModeOff(), } end end; setState = function(self, state) self.state = state self.bAttacking = (self.state == CHR_ATTACK) self:updateBitmap() end; tick = function(self) if (self.charging > 0) then self.charging = self.charging - 1 end Character.tick(self) end; died = function(self, killer, damageType, location) Character.died(self, killer, damageType, location) if (killer) then self:log("Killed by "..killer:toString()..".") else self:log("Commited suicide.") end ActionController:addSequence({ ActionExModeOn(), ActionWait(200), ActionSetVariable(game, "game_over", 1), ActionAddSequence({ ActionTweenVariable(game, "game_over_alpha", 300, 255, 0), }), }) end; event_bumped_into = function(self, obj) -- Players move away for other players who try to enter this tile if (obj:instanceOf(Player)) then self:moveAway() end end; gainExperience = function(self, xp) self.experience = self.experience + xp if (self.experience >= self.nextLevelExperience) then self.endurance = self.endurance + 5 self.nextLevelExperience = 2.5 * self.nextLevelExperience self:derive_attributes() end end; defaultproperties = { sleepBitmap = nil, strength = 5, dexterity = 5, agility = 5, endurance = 5, experience = 0, nextLevelExperience = 31, attack_min_dam = 5, attack_max_dam = 10, charging = 0, state = CHR_READY, draw_mode = DM_ALPHA, tick_time = 1, travel = 1, -- Player can travel to other maps charAnim = extr_char_anim(m_get_bitmap("frode.tga")), }; } --- NEW FILE: Torch.lua --- -- -- A torch by Frode -- import("Decoration.lua") import("Animation.lua") import("lang.lua") Torch = Decoration:subclass { name = "Torch"; defaultproperties = { animType = LinearAnimation, animSeq = { m_get_bitmap("torch1.bmp"), m_get_bitmap("torch2.bmp"), m_get_bitmap("torch3.bmp"), m_get_bitmap("torch4.bmp"), m_get_bitmap("torch5.bmp"), m_get_bitmap("torch6.bmp"), }, animSpeed = 1 / 10, draw_mode = DM_MASKED, convTableKeyword = "Fire", }; } --- NEW FILE: Turtle.lua --- -- Turtle Turtle = Enemy:subclass { name = "Turtle"; bPlaceable = true; defaultproperties = { attackMinDam = 1, attackMaxDam = 4, maxHealth = 50, speed = 1, experience = 20, offset_y = 4, draw_mode = DM_MASKED, charAnim = extr_char_anim(m_get_bitmap("turtle.bmp"), 26, 14), deathBitmap = m_get_bitmap("turtle_dead.bmp"), nature = AGGRESSIVE, controllerClass = AdvAIRandom, hitEffectHeight = 0, }; } --- NEW FILE: Viewport.lua --- import("Object.lua") Viewport = Object:subclass { name = "Viewport"; init = function(self, x, y, w, h) self.x = x or self.x self.y = y or self.y self.w = w or self.w self.h = h or self.h end; mapToScreen = function(self, x, y, z) if (not self.target or not self.target.map) then return end if (not z) then z = 0 end return m_map_to_screen( x, y, z, self.x, self.y, self.w, self.h, self.target.x, self.target.y, self.target.map ) end; screenToMap = function(self, x, y) if (not self.target or not self.target.map) then return end return m_screen_to_map( x, y, self.x, self.y, self.w, self.h, self.target.x, self.target.y, self.target.map ) end; render = function(self) if (not self.target or not self.target.map) then return end if (self.target) then m_draw_viewport( self.x, self.y, self.w, self.h, self.target.x, self.target.y, self.target.map ) end end; defaultproperties = { x = 0, y = 0, w = 0, h = 0, target = nil, }; } Index: Action.lua =================================================================== RCS file: /cvsroot/moeng/CaveAdventure/data/scripts/Action.lua,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Action.lua 1 Jun 2003 00:14:17 -0000 1.2 --- Action.lua 13 Jan 2004 19:20:08 -0000 1.3 *************** *** 4,19 **** -- actions for your own sequences. -- ! -- All actions have a finished() function indicating whether they ! -- are finished. Non-instant actions also have an exec() function ! -- that will be called every game tick until their finished() ! -- function returns 1. -- -- A summaration of the available action types follows: -- -- ActionSequence(sequence) -- ActionAddSequence(sequence) -- ActionCallFunction(f, ...) -- ActionSetVariable(table, key, value) ! -- ActionTweenVariable(table, key, time, to [, from]) -- ActionWait(duration) -- --- 4,18 ---- -- actions for your own sequences. -- ! -- All actions have an exec() function that will be called every ! -- game tick until it has returned true. -- -- A summaration of the available action types follows: -- -- ActionSequence(sequence) + -- ActionParallel(sequence) -- ActionAddSequence(sequence) -- ActionCallFunction(f, ...) -- ActionSetVariable(table, key, value) ! -- ActionTweenVariable(table, key, time, to [, from, func]) -- ActionWait(duration) -- *************** *** 21,28 **** --- 20,29 ---- -- ActionChangeDirection(actor, new_direction) -- ActionWalk(actor, direction, amount [,col]) + -- ActionWalkPath(actor, path [,col]) -- ActionConversation(conversation) -- ActionExModeOn() -- ActionExModeOff() -- ActionPlaySong(filename, fadeTime [, wait]) + -- ActionPlaySample(filename) -- ActionFadeOutMusic(fadeTime [, wait]) -- ActionFadeInMusic(filename, fadeTime [, wait]) *************** *** 30,41 **** -- ActionFadeOutMap(time) -- ActionSetState(object, state) ! -- ActionSetPosition(actor, x, y [, dir]) ! -- ActionChangeMap(filename) -- ActionDestroyObject(object) -- ActionAddObject({name|class}, x, y) -- ActionQuitGame() -- ActionShowMapName(bitmap) -- ! -- By Bjørn Lindeijer --- 31,42 ---- -- ActionFadeOutMap(time) -- ActionSetState(object, state) ! -- ActionSetPosition(actor, x, y [,dir[,map]]) -- ActionDestroyObject(object) -- ActionAddObject({name|class}, x, y) -- ActionQuitGame() -- ActionShowMapName(bitmap) + -- ActionSetCameraTarget(target [, tween]) -- ! -- By Bjorn Lindeijer *************** *** 51,55 **** -- The exec function will be called every game tick until it returns true. ! exec = function(self) end; } --- 52,56 ---- -- The exec function will be called every game tick until it returns true. ! exec = function(self) return true; end; } *************** *** 84,87 **** --- 85,127 ---- } + ActionParallel = Action:subclass + { + name = "ActionParallel"; + + init = function(self, actions) + m_message("ActionParallel initializing with ".. table.getn(actions) .." actions.") + self.actions = {} + + -- Add all actions to the list of actions to execute. + local i + for i = 1, table.getn(actions) do + if (actions[i] and actions[i]:instanceOf(Action)) then + -- Create an action execution environment for this action + local execEnv = {} + setmetatable(execEnv, {__index = actions[i]}) + + -- Insert the action execution environment in the actions array + table.insert(self.actions, execEnv) + else + m_message("ActionParallel: action not an instance of Action (".. actions[i].name ..")") + end + end + end; + + exec = function(self) + local i + + -- Execute all running actions + for i = 1, table.getn(self.actions) do + if (i <= table.getn(self.actions) and self.actions[i]:exec()) then + m_message("ActionParallel finished executing "..self.actions[i].name) + table.remove(self.actions, i) + i = i - 1 + end + end + + return table.getn(self.actions) == 0 + end; + } -- Add a sequence to the sequence controller *************** *** 114,118 **** exec = function(self) ! self.f(expand(self.arg)) return true end; --- 154,158 ---- exec = function(self) ! self.f(unpack(self.arg)) return true end; *************** *** 145,154 **** name = "ActionTweenVariable"; ! init = function(self, table, key, time, to, from) self.table = table self.key = key self.time = time self.to = to ! self.from = from self.count = 0 --- 185,201 ---- name = "ActionTweenVariable"; ! init = function(self, table, key, time, to, from, func) self.table = table self.key = key self.time = time self.to = to ! if (type(from) == "number") then self.from = from end ! if (type(from) == "function") then self.func = from end ! if (type(func) == "function") then self.func = func end ! if (not self.func) then ! self.func = function(from, to, perc) ! return from + perc * (to - from) ! end ! end self.count = 0 *************** *** 157,166 **** exec = function(self) if (not self.from) then self.from = self.table[self.key] end ! self.count = self.count + 1 if (self.count <= self.time) then ! self.table[self.key] = self.from + ((self.count / self.time) * (self.to - self.from)) else ! self.table[self.key] = self.to end --- 204,214 ---- exec = function(self) if (not self.from) then self.from = self.table[self.key] end ! if (not self.from) then return true end ! self.count = self.count + 1 if (self.count <= self.time) then ! self.table[self.key] = self.func(self.from, self.to, (self.count / self.time)) else ! self.table[self.key] = self.func(self.from, self.to, 1) end *************** *** 219,223 **** self.direction = direction self.amount = amount ! self.col = (col ~= nil and col ~= 0) end; --- 267,272 ---- self.direction = direction self.amount = amount ! self.col = col ! if (col == 0) then self.col = false end end; *************** *** 237,240 **** --- 286,320 ---- + -- Order characters around using a path string + + ActionWalkPath = ActionSequence:subclass + { + name = "ActionWalkPath"; + + init = function(self, object, path, col) + if (type(object) ~= "table") then error("Invalid object passed to ActionWalkPath") end + if (type(path) ~= "string") then error("Invalid string passed to ActionWalkPath") end + + self.actions = {} + + for w in string.gfind(path, "[UDLR]%d*") do + local dir = string.sub(w,1,1) + if (dir == "U") then dir = DIR_UP end + if (dir == "R") then dir = DIR_RIGHT end + if (dir == "D") then dir = DIR_DOWN end + if (dir == "L") then dir = DIR_LEFT end + + local amount = tonumber(string.sub(w,2)) + if (not amount or amount == 0) then amount = 1 end + + table.insert(self.actions, ActionWalk(object, dir, amount, col)) + end + + self.i = 1 + end; + } + + + -- Show conversations within a sequence *************** *** 253,257 **** self.started = true end ! return (ConvBox.state == CB_CLOSED and self.started) end; } --- 333,337 ---- self.started = true end ! return (convBox.state == CB_CLOSED and self.started) end; } *************** *** 283,286 **** --- 363,368 ---- table.remove(exModeArray, table.getn(exModeArray)) --m_message("Exclusive mode turned off (".. table.getn(exModeArray) ..")") + else + m_set_ex_mode(0) end return true *************** *** 289,309 **** - -- Change to another map - - ActionChangeMap = Action:subclass - { - name = "ActionChangeMap"; - - init = function(self, filename) - self.filename = filename - end; - - exec = function(self) - m_load_map(self.filename) - return true - end; - } - - -- Fading in and out --- 371,374 ---- *************** *** 333,349 **** name = "ActionSetPosition"; ! init = function(self, obj, x, y, dir) self.x = x self.y = y self.dir = dir self.obj = obj end; exec = function(self) ! self.obj.x = self.x ! self.obj.y = self.y ! if self.dir ~= nil then self.obj.dir = self.dir end --- 398,417 ---- name = "ActionSetPosition"; ! init = function(self, obj, x, y, dir, map) self.x = x self.y = y self.dir = dir self.obj = obj + self.map = map end; exec = function(self) ! self.obj:setPosition(self.x, self.y) ! if (self.dir) then self.obj.dir = self.dir + if (self.map) then + self.obj:setMap(self.map) + end end *************** *** 376,379 **** --- 444,459 ---- } + ActionPlaySample = ActionCallFunction:subclass + { + name = "ActionPlaySample"; + + init = function(self, filename) + if (not filename) then + error("Error: ActionPlaySample created without a filename") + end + ActionCallFunction.init(self, m_play_sample, filename) + end; + } + ActionFadeOutMusic = Action:subclass *************** *** 474,478 **** m_add_object(self.x, self.y, self.objname) else ! spawn(self.x, self.y, self.objname) end return true --- 554,558 ---- m_add_object(self.x, self.y, self.objname) else ! Actor:spawn(self.objname, self.x, self.y) end return true *************** *** 503,522 **** init = function(self, bitmap) self.bitmap = bitmap end; exec = function(self) ! -- Make sure no other ActionShowMapName sequence is taking place ! ActionController:removeSequence(show_map_seq) - -- Start a new show_map_seq = ActionController:addSequence{ ! ActionWait(50), ! ActionSetVariable(HUD, "map_name", self.bitmap), ! ActionTweenVariable(HUD, "map_name_alpha", 100, 255, 0), ! ActionWait(200), ! ActionTweenVariable(HUD, "map_name_alpha", 100, 0, 255), } return true end; --- 583,623 ---- init = function(self, bitmap) + if (not bitmap) then + self:log("Warning: no valid bitmap for showing map name!") + end self.bitmap = bitmap end; exec = function(self) ! --[[ ! local mapInt = BBRpgMapname() ! ! mapInt.bitmap = self.bitmap show_map_seq = ActionController:addSequence{ ! ActionCallFunction(interactionMaster.addInteraction, interactionMaster, mapInt), ! ActionTweenVariable(mapInt, "perc", 50, 1, 0), ! ActionWait(100), ! ActionTweenVariable(mapInt, "perc", 50, 0, 1), ! ActionCallFunction(interactionMaster.removeInteraction, interactionMaster, mapInt), } + ]] + + return true + end; + } + + ActionSetCameraTarget = Action:subclass + { + name = "ActionSetCameraTarget"; + + init = function(self, target, tween) + self.target = target + self.tween = tween + end; + + exec = function(self) + gameCameraTarget:setTarget(self.target, self.tween) return true end; Index: Pawn.lua =================================================================== RCS file: /cvsroot/moeng/CaveAdventure/data/scripts/Pawn.lua,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Pawn.lua 1 Jun 2003 17:27:24 -0000 1.2 --- Pawn.lua 13 Jan 2004 19:20:08 -0000 1.3 *************** *** 1,113 **** ! -- ! -- A base class for anything that walks like a character ! -- By Bjørn Lindeijer ! ! import("Actor.lua") ! ! ! Pawn = Actor:subclass ! { ! name = "Pawn"; ! ! init = function(self) ! self.health = self.maxHealth ! ! -- Create the default controller, if present ! if (not self.controller and self.controllerClass) then ! self.controller = self.controllerClass() ! self.controller:possess(self) ! end ! end; ! ! tick = function(self) ! Actor.tick(self) ! if (self.controller) then ! self.controller:tick() ! end ! end; ! ! ! --== BEING POSSESSED ==-- ! ! possessedBy = function(self, controller) ! self.controller = controller ! end; ! ! unPossessed = function(self) ! self.controller = nil ! end; ! ! ! --== TAKING DAMAGE ==-- ! ! takeDamage = function(self, damage, instigator, damageType, momentum, location) ! if (damage > 0) then ! local actualDamage = damage ! self.health = self.health - damage ! ! if (self.health <= 0) then ! -- Pawn died ! local killer ! if (instigator) then ! killer = instigator.controller ! end ! self:died(killer, damageType, location) ! else ! if (self.controller) then ! self.controller:notifyTakeDamage(actualDamage, instigator, damageType, momentum, location); ! end ! end ! ! self:makeNoise(15) ! end ! end; ! ! died = function(self, killer, damageType, location) ! -- Become bleeding body and fade away (implement in subclass) ! end; ! ! ! --== MOVING ==-- ! ! walk = function(self, dir, no_collision) ! if (self.walking == 0) then ! if (no_collision) then ! m_walk_obj_nocol(self, dir) ! else ! m_walk_obj(self, dir) ! end ! if (self.walking ~= 0) then ! self:makeNoise(10) ! end ! end ! end; ! ! attack = function(self) ! -- Implement in subclass ! end; ! ! -- Making noise will cause surrounding Pawns to hear the noise with ! -- hearedLoudness = max(0.1, loudness / (distanceInTiles ^ 2)) ! makeNoise = function(self, loudness) ! end; ! ! hearNoise = function(self, loudness, noiseMaker) ! if (self.controller) then ! self.controller:notifyHearNoise(loadness, noiseMaker) ! end ! end; ! ! ! defaultproperties = { ! -- The Controller possessing this Pawn ! controller = nil, ! ! maxHealth = 100, ! speed = 3, ! offset_y = -6, ! draw_mode = DM_ALPHA, ! obstacle = 1, ! ! controllerClass = nil, ! }; ! } --- 1,167 ---- ! -- ! -- A base class for anything that walks like a character ! -- By Bjorn Lindeijer ! ! import("Actor.lua") ! import("BloodSplat.lua") ! ! ! Pawn = Actor:subclass ! { ! name = "Pawn"; ! ! init = function(self) ! self.health = self.maxHealth ! ! -- Create the default controller, if present ! if (not self.controller and self.controllerClass) then ! self.controller = self.controllerClass() ! self.controller:possess(self) ! end ! ! Actor.init(self) ! end; ! ! tick = function(self) ! Actor.tick(self) ! if (self.controller) then ! self.controller:tick() ! end ! end; ! ! ! ! --== BEING POSSESSED ==-- ! ! possessedBy = function(self, controller) ! self.controller = controller ! end; ! ! unPossessed = function(self) ! self.controller = nil ! end; ! ! ! --== TAKING DAMAGE ==-- ! ! takeDamage = function(self, damage, instigator, damageType, momentum, location) ! self:log("takes "..damage.." damage") ! if (damage > 0) then ! local actualDamage = damage ! self.health = self.health - actualDamage ! ! -- Some blood flying around maybe? ! if (not self.bDead and self.hitEffectClass) then ! local obj = self:spawn(self.hitEffectClass, self.x, self.y) ! obj.offset_z = obj.offset_z + self.hitEffectHeight ! end ! ! -- A scream perhaps? ! if (table.getn(self.hitSounds) > 0) then ! local sampleFile = self.hitSounds[math.random(table.getn(self.hitSounds))] ! m_play_sample(sampleFile) ! end ! ! if (self.health <= 0 and not self.bDead) then ! -- Pawn died ! self:died(instigator, damageType, location) ! elseif (self.controller) then ! self.controller:notifyTakeDamage(actualDamage, instigator, damageType, momentum, location); ! end ! ! self:makeNoise(15) ! end ! end; ! ! died = function(self, killer, damageType, location) ! self.bDead = true ! -- Become bleeding body and fade away (implement in subclass) ! end; ! ! ! --== MOVING ==-- ! ! walk = function(self, dir, no_collision) ! if (self.walking == 0) then ! if (no_collision) then ! m_walk_obj_nocol(self, dir) ! else ! m_walk_obj(self, dir) ! end ! if (self.walking ~= 0) then ! self:makeNoise(10) ! end ! end ! end; ! ! -- Ask this pawn to move away, he'll move away if possible ! moveAway = function(self) ! if (not self.bSleeping and self.walking == 0) then ! local dir = self:randomFreeTileAround() ! if (dir) then ! self:walk(dir) ! end ! end ! end; ! ! ! attack = function(self) ! -- Implement in subclass ! end; ! ! -- Making noise will cause surrounding Pawns to hear the noise with ! -- hearedLoudness = max(0.1, min(loudness, loudness / (distanceInTiles ^ 2))) ! makeNoise = function(self, loudness) ! m_make_noise(self, loudness) ! end; ! ! hearNoise = function(self, loudness, noiseMaker) ! --self:log("Heared noise with loudness "..loudness.." from "..noiseMaker:toString()) ! if (self.controller) then ! self.controller:notifyHearNoise(loudness, noiseMaker) ! end ! end; ! ! -- This actor bumps into an obstacle ! event_bump_into = function(self, obj) ! if (self.controller) then ! self.controller:notifyBumpInto(obj) ! end ! end; ! ! -- Another actor bumps into this actor ! event_bumped_into = function(self, obj) ! if (self.controller) then ! self.controller:notifyBumpedInto(obj) ! end ! end; ! ! -- This actor finishes its current walking step ! event_walk_finished = function(self) ! if (self.controller) then ! self.controller:notifyWalkFinished(obj) ! end ! end; ! ! ! defaultproperties = { ! bSleeping = false, ! bDead = false, ! ! -- The Controller possessing this Pawn ! controller = nil, ! ! maxHealth = 100, ! speed = 3, ! --offset_y = -6, ! draw_mode = DM_ALPHA, ! obstacle = 1, ! bCenterBitmap = true, ! ! hitSounds = {}, ! hitEffectClass = BloodSplat, ! hitEffectHeight = 24, ! controllerClass = nil, ! bCenterOnTile = true, ! }; ! } |