mirror of
https://github.com/evennia/evennia.git
synced 2026-04-05 15:37:17 +02:00
Fixing tutorial world usage of search.
This commit is contained in:
parent
59ccd3eb38
commit
1b0544c261
3 changed files with 227 additions and 227 deletions
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
This module implements a simple mobile object with
|
||||
This module implements a simple mobile object with
|
||||
a very rudimentary AI as well as an aggressive enemy
|
||||
object based on that mobile class.
|
||||
object based on that mobile class.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -16,10 +16,10 @@ BASE_CHARACTER_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
|
|||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Mob - mobile object
|
||||
# Mob - mobile object
|
||||
#
|
||||
# This object utilizes exits and moves about randomly from
|
||||
# room to room.
|
||||
# room to room.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ class Mob(tut_objects.TutorialObject):
|
|||
"""
|
||||
This type of mobile will roam from exit to exit at
|
||||
random intervals. Simply lock exits against the is_mob attribute
|
||||
to block them from the mob (lockstring = "traverse:not attr(is_mob)").
|
||||
to block them from the mob (lockstring = "traverse:not attr(is_mob)").
|
||||
"""
|
||||
def at_object_creation(self):
|
||||
"This is called when the object is first created."
|
||||
|
|
@ -35,11 +35,11 @@ class Mob(tut_objects.TutorialObject):
|
|||
|
||||
self.scripts.add(tut_scripts.IrregularEvent)
|
||||
# this is a good attribute for exits to look for, to block
|
||||
# a mob from entering certain exits.
|
||||
self.db.is_mob = True
|
||||
self.db.last_location = None
|
||||
# only when True will the mob move.
|
||||
self.db.roam_mode = True
|
||||
# a mob from entering certain exits.
|
||||
self.db.is_mob = True
|
||||
self.db.last_location = None
|
||||
# only when True will the mob move.
|
||||
self.db.roam_mode = True
|
||||
|
||||
def announce_move_from(self, destination):
|
||||
"Called just before moving"
|
||||
|
|
@ -53,8 +53,8 @@ class Mob(tut_objects.TutorialObject):
|
|||
"Called at irregular intervals. Moves the mob."
|
||||
if self.roam_mode:
|
||||
exits = [ex for ex in self.location.exits if ex.access(self, "traverse")]
|
||||
if exits:
|
||||
# Try to make it so the mob doesn't backtrack.
|
||||
if exits:
|
||||
# Try to make it so the mob doesn't backtrack.
|
||||
new_exits = [ex for ex in exits if ex.destination != self.db.last_location]
|
||||
if new_exits:
|
||||
exits = new_exits
|
||||
|
|
@ -67,15 +67,15 @@ class Mob(tut_objects.TutorialObject):
|
|||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Enemy - mobile attacking object
|
||||
# Enemy - mobile attacking object
|
||||
#
|
||||
# An enemy is a mobile that is aggressive against players
|
||||
# in its vicinity. An enemy will try to attack characters
|
||||
# An enemy is a mobile that is aggressive against players
|
||||
# in its vicinity. An enemy will try to attack characters
|
||||
# in the same location. It will also pursue enemies through
|
||||
# exits if possible.
|
||||
# exits if possible.
|
||||
#
|
||||
# An enemy needs to have a Weapon object in order to
|
||||
# attack.
|
||||
# An enemy needs to have a Weapon object in order to
|
||||
# attack.
|
||||
#
|
||||
# This particular tutorial enemy is a ghostly apparition that can only
|
||||
# be hurt by magical weapons. It will also not truly "die", but only
|
||||
|
|
@ -90,44 +90,44 @@ class AttackTimer(Script):
|
|||
"""
|
||||
def at_script_creation(self):
|
||||
"This sets up the script"
|
||||
self.key = "AttackTimer"
|
||||
self.key = "AttackTimer"
|
||||
self.desc = "Drives an Enemy's combat."
|
||||
self.interval = random.randint(2, 3) # how fast the Enemy acts
|
||||
self.interval = random.randint(2, 3) # how fast the Enemy acts
|
||||
self.start_delay = True # wait self.interval before first call
|
||||
self.persistent = True
|
||||
self.persistent = True
|
||||
|
||||
def at_repeat(self):
|
||||
"Called every self.interval seconds."
|
||||
"Called every self.interval seconds."
|
||||
if self.obj.db.inactive:
|
||||
return
|
||||
return
|
||||
#print "attack timer: at_repeat", self.dbobj.id, self.ndb.twisted_task, id(self.ndb.twisted_task)
|
||||
if self.obj.db.roam_mode:
|
||||
if self.obj.db.roam_mode:
|
||||
self.obj.roam()
|
||||
#return
|
||||
elif self.obj.db.battle_mode:
|
||||
#print "attack"
|
||||
self.obj.attack()
|
||||
return
|
||||
return
|
||||
elif self.obj.db.pursue_mode:
|
||||
#print "pursue"
|
||||
self.obj.pursue()
|
||||
#return
|
||||
else:
|
||||
#dead mode. Wait for respawn.
|
||||
#dead mode. Wait for respawn.
|
||||
dead_at = self.db.dead_at
|
||||
if not dead_at:
|
||||
self.db.dead_at = time.time()
|
||||
if (time.time() - self.db.dead_at) > self.db.dead_timer:
|
||||
self.obj.reset()
|
||||
|
||||
|
||||
class Enemy(Mob):
|
||||
"""
|
||||
This is a ghostly enemy with health (hit points). Their chance to hit, damage etc is
|
||||
determined by the weapon they are wielding, same as characters.
|
||||
|
||||
An enemy can be in four modes:
|
||||
An enemy can be in four modes:
|
||||
roam (inherited from Mob) - where it just moves around randomly
|
||||
battle - where it stands in one place and attacks players
|
||||
battle - where it stands in one place and attacks players
|
||||
pursue - where it follows a player, trying to enter combat again
|
||||
dead - passive and invisible until it is respawned
|
||||
|
||||
|
|
@ -139,19 +139,19 @@ class Enemy(Mob):
|
|||
defeat_text_room - text to show other players in room when a player is defeated
|
||||
win_text - text to show player when defeating the enemy
|
||||
win_text_room - text to show room when a player defeates the enemy
|
||||
respawn_text - text to echo to room when the mob is reset/respawn in that room.
|
||||
respawn_text - text to echo to room when the mob is reset/respawn in that room.
|
||||
|
||||
"""
|
||||
def at_object_creation(self):
|
||||
"Called at object creation."
|
||||
super(Enemy, self).at_object_creation()
|
||||
|
||||
|
||||
self.db.tutorial_info = "This moving object will attack players in the same room."
|
||||
|
||||
# state machine modes
|
||||
|
||||
# state machine modes
|
||||
self.db.roam_mode = True
|
||||
self.db.battle_mode = False
|
||||
self.db.pursue_mode = False
|
||||
self.db.pursue_mode = False
|
||||
self.db.dead_mode = False
|
||||
# health (change this at creation time)
|
||||
self.db.full_health = 20
|
||||
|
|
@ -159,8 +159,8 @@ class Enemy(Mob):
|
|||
self.db.dead_at = time.time()
|
||||
self.db.dead_timer = 100 # how long to stay dead
|
||||
self.db.inactive = True # this is used during creation to make sure the mob doesn't move away
|
||||
# store the last player to hit
|
||||
self.db.last_attacker = None
|
||||
# store the last player to hit
|
||||
self.db.last_attacker = None
|
||||
# where to take defeated enemies
|
||||
self.db.defeat_location = "darkcell"
|
||||
self.scripts.add(AttackTimer)
|
||||
|
|
@ -169,26 +169,26 @@ class Enemy(Mob):
|
|||
"the irregular event is inherited from Mob class"
|
||||
strings = self.db.irregular_echoes
|
||||
if strings:
|
||||
self.location.msg_contents(strings[random.randint(0, len(strings) - 1)])
|
||||
self.location.msg_contents(strings[random.randint(0, len(strings) - 1)])
|
||||
|
||||
def roam(self):
|
||||
"Called by Attack timer. Will move randomly as long as exits are open."
|
||||
|
||||
# in this mode, the mob is healed.
|
||||
# in this mode, the mob is healed.
|
||||
self.db.health = self.db.full_health
|
||||
players = [obj for obj in self.location.contents
|
||||
players = [obj for obj in self.location.contents
|
||||
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
|
||||
if players:
|
||||
# we found players in the room. Attack.
|
||||
self.db.roam_mode = False
|
||||
if players:
|
||||
# we found players in the room. Attack.
|
||||
self.db.roam_mode = False
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = True
|
||||
self.db.battle_mode = True
|
||||
|
||||
elif random.random() < 0.2:
|
||||
# no players to attack, move about randomly.
|
||||
exits = [ex.destination for ex in self.location.exits if ex.access(self, "traverse")]
|
||||
if exits:
|
||||
# Try to make it so the mob doesn't backtrack.
|
||||
if exits:
|
||||
# Try to make it so the mob doesn't backtrack.
|
||||
new_exits = [ex for ex in exits if ex.destination != self.db.last_location]
|
||||
if new_exits:
|
||||
exits = new_exits
|
||||
|
|
@ -198,7 +198,7 @@ class Enemy(Mob):
|
|||
else:
|
||||
# no exits - a dead end room. Respawn back to start.
|
||||
self.move_to(self.home)
|
||||
|
||||
|
||||
def attack(self):
|
||||
"""
|
||||
This is the main mode of combat. It will try to hit players in
|
||||
|
|
@ -206,11 +206,11 @@ class Enemy(Mob):
|
|||
to the defeat location.
|
||||
"""
|
||||
last_attacker = self.db.last_attacker
|
||||
players = [obj for obj in self.location.contents
|
||||
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
|
||||
players = [obj for obj in self.location.contents
|
||||
if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
|
||||
if players:
|
||||
|
||||
# find a target
|
||||
|
||||
# find a target
|
||||
if last_attacker in players:
|
||||
# prefer to attack the player last attacking.
|
||||
target = last_attacker
|
||||
|
|
@ -226,7 +226,7 @@ class Enemy(Mob):
|
|||
# analyze result.
|
||||
if target.db.health <= 0:
|
||||
# we reduced enemy to 0 health. Whisp them off to the prison room.
|
||||
tloc = search_object(self.db.defeat_location, global_search=True)
|
||||
tloc = search_object(self.db.defeat_location)
|
||||
tstring = self.db.defeat_text
|
||||
if not tstring:
|
||||
tstring = "You feel your conciousness slip away ... you fall to the ground as "
|
||||
|
|
@ -240,24 +240,24 @@ class Enemy(Mob):
|
|||
target.location = tloc[0]
|
||||
tloc[0].at_object_receive(target, self.location)
|
||||
elif not ostring:
|
||||
ostring = "%s falls to the ground!" % target.key
|
||||
ostring = "%s falls to the ground!" % target.key
|
||||
self.location.msg_contents(ostring, exclude=[target])
|
||||
else:
|
||||
# no players found, this could mean they have fled. Switch to pursue mode.
|
||||
self.battle_mode = False
|
||||
self.roam_mode = False
|
||||
self.pursue_mode = True
|
||||
|
||||
|
||||
def pursue(self):
|
||||
"""
|
||||
In pursue mode, the enemy tries to find players in adjoining rooms, preferably
|
||||
those that previously attacked it.
|
||||
those that previously attacked it.
|
||||
"""
|
||||
last_attacker = self.db.last_attacker
|
||||
players = [obj for obj in self.location.contents if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
|
||||
players = [obj for obj in self.location.contents if utils.inherits_from(obj, BASE_CHARACTER_TYPECLASS) and not obj.is_superuser]
|
||||
if players:
|
||||
# we found players in the room. Maybe we caught up with some, or some walked in on us
|
||||
# before we had time to pursue them. Switch to battle mode.
|
||||
# before we had time to pursue them. Switch to battle mode.
|
||||
self.battle_mode = True
|
||||
self.roam_mode = False
|
||||
self.pursue_mode = False
|
||||
|
|
@ -266,43 +266,43 @@ class Enemy(Mob):
|
|||
destinations = [ex.destination for ex in self.location.exits if ex.access(self, "traverse")]
|
||||
# find all players in the possible destinations. OBS-we cannot just use the player's
|
||||
# current position to move the Enemy; this might have changed when the move is performed,
|
||||
# causing the enemy to teleport out of bounds.
|
||||
# causing the enemy to teleport out of bounds.
|
||||
players = {}
|
||||
for dest in destinations:
|
||||
for obj in [o for o in dest.contents if utils.inherits_from(o, BASE_CHARACTER_TYPECLASS)]:
|
||||
players[obj] = dest
|
||||
players[obj] = dest
|
||||
if players:
|
||||
# we found targets. Move to intercept.
|
||||
if last_attacker in players:
|
||||
# preferably the one that last attacked us
|
||||
self.move_to(players[last_attacker])
|
||||
else:
|
||||
# otherwise randomly.
|
||||
# otherwise randomly.
|
||||
key = players.keys()[random.randint(0, len(players) - 1)]
|
||||
self.move_to(players[key])
|
||||
else:
|
||||
# we found no players nearby. Return to roam mode.
|
||||
# we found no players nearby. Return to roam mode.
|
||||
self.battle_mode = False
|
||||
self.roam_mode = True
|
||||
self.pursue_mode = False
|
||||
|
||||
|
||||
def at_hit(self, weapon, attacker, damage):
|
||||
"""
|
||||
Called when this object is hit by an enemy's weapon
|
||||
Should return True if enemy is defeated, False otherwise.
|
||||
|
||||
In the case of players attacking, we handle all the events
|
||||
and information from here, so the return value is not used.
|
||||
and information from here, so the return value is not used.
|
||||
"""
|
||||
|
||||
self.db.last_attacker = attacker
|
||||
self.db.last_attacker = attacker
|
||||
if not self.db.battle_mode:
|
||||
# we were attacked, so switch to battle mode.
|
||||
self.db.roam_mode = False
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = True
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = True
|
||||
#self.scripts.add(AttackTimer)
|
||||
|
||||
|
||||
if not weapon.db.magic:
|
||||
# In the tutorial, the enemy is a ghostly apparition, so
|
||||
# only magical weapons can harm it.
|
||||
|
|
@ -310,7 +310,7 @@ class Enemy(Mob):
|
|||
if not string:
|
||||
string = "Your weapon just passes through your enemy, causing no effect!"
|
||||
attacker.msg(string)
|
||||
return
|
||||
return
|
||||
else:
|
||||
# an actual hit
|
||||
health = float(self.db.health)
|
||||
|
|
@ -319,10 +319,10 @@ class Enemy(Mob):
|
|||
if health <= 0:
|
||||
string = self.db.win_text
|
||||
if not string:
|
||||
string = "After your last hit, %s folds in on itself, it seems to fade away into nothingness. " % self.key
|
||||
string = "After your last hit, %s folds in on itself, it seems to fade away into nothingness. " % self.key
|
||||
string += "In a moment there is nothing left but the echoes of its screams. But you have a "
|
||||
string += "feeling it is only temporarily weakened. "
|
||||
string += "You fear it's only a matter of time before it materializes somewhere again."
|
||||
string += "You fear it's only a matter of time before it materializes somewhere again."
|
||||
attacker.msg(string)
|
||||
string = self.db.win_text_room
|
||||
if not string:
|
||||
|
|
@ -331,28 +331,28 @@ class Enemy(Mob):
|
|||
string += "feeling it is only temporarily weakened. "
|
||||
string += "You fear it's only a matter of time before it materializes somewhere again."
|
||||
self.location.msg_contents(string, exclude=[attacker])
|
||||
|
||||
# put enemy in dead mode and hide it from view. IrregularEvent will bring it back later.
|
||||
|
||||
# put enemy in dead mode and hide it from view. IrregularEvent will bring it back later.
|
||||
self.db.roam_mode = False
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = False
|
||||
self.db.dead_mode = True
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = False
|
||||
self.db.dead_mode = True
|
||||
self.db.dead_at = time.time()
|
||||
self.location = None
|
||||
self.location = None
|
||||
else:
|
||||
self.location.msg_contents("%s wails, shudders and writhes." % self.key)
|
||||
return False
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
"If the mob was 'dead', respawn it to its home position and reset all modes and damage."
|
||||
if self.db.dead_mode:
|
||||
self.db.health = self.db.full_health
|
||||
self.db.roam_mode = True
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = False
|
||||
self.db.dead_mode = False
|
||||
self.location = self.home
|
||||
self.db.pursue_mode = False
|
||||
self.db.battle_mode = False
|
||||
self.db.dead_mode = False
|
||||
self.location = self.home
|
||||
string = self.db.respawn_text
|
||||
if not string:
|
||||
if not string:
|
||||
string = "%s fades into existence from out of thin air. It's looking pissed." % self.key
|
||||
self.location.msg_contents(string)
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
"""
|
||||
TutorialWorld - basic objects - Griatch 2011
|
||||
|
||||
This module holds all "dead" object definitions for
|
||||
the tutorial world. Object-commands and -cmdsets
|
||||
This module holds all "dead" object definitions for
|
||||
the tutorial world. Object-commands and -cmdsets
|
||||
are also defined here, together with the object.
|
||||
|
||||
Objects:
|
||||
Objects:
|
||||
|
||||
TutorialObject
|
||||
|
||||
Readable
|
||||
Readable
|
||||
Climbable
|
||||
Obelisk
|
||||
LightSource
|
||||
Obelisk
|
||||
LightSource
|
||||
CrumblingWall
|
||||
Weapon
|
||||
Weapon
|
||||
WeaponRack
|
||||
|
||||
"""
|
||||
|
||||
import time, random
|
||||
import time, random
|
||||
|
||||
from ev import utils, create_object
|
||||
from ev import Object, Exit, Command, CmdSet, Script
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# TutorialObject
|
||||
# TutorialObject
|
||||
#
|
||||
# The TutorialObject is the base class for all items
|
||||
# in the tutorial. They have an attribute "tutorial_info"
|
||||
|
|
@ -35,7 +35,7 @@ from ev import Object, Exit, Command, CmdSet, Script
|
|||
#
|
||||
# TutorialObjects may also be "reset". What the reset means
|
||||
# is up to the object. It can be the resetting of the world
|
||||
# itself, or the removal of an inventory item from a
|
||||
# itself, or the removal of an inventory item from a
|
||||
# character's inventory when leaving the tutorial, for example.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
|
@ -51,7 +51,7 @@ class TutorialObject(Object):
|
|||
super(TutorialObject, self).at_object_creation()
|
||||
self.db.tutorial_info = "No tutorial info is available for this object."
|
||||
#self.db.last_reset = time.time()
|
||||
|
||||
|
||||
def reset(self):
|
||||
"Resets the object, whatever that may mean."
|
||||
self.location = self.home
|
||||
|
|
@ -59,13 +59,13 @@ class TutorialObject(Object):
|
|||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Readable - an object one can "read".
|
||||
# Readable - an object one can "read".
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class CmdRead(Command):
|
||||
"""
|
||||
Usage:
|
||||
Usage:
|
||||
read [obj]
|
||||
|
||||
Read some text.
|
||||
|
|
@ -82,8 +82,8 @@ class CmdRead(Command):
|
|||
else:
|
||||
obj = self.obj
|
||||
if not obj:
|
||||
return
|
||||
# we want an attribute read_text to be defined.
|
||||
return
|
||||
# we want an attribute read_text to be defined.
|
||||
readtext = obj.db.readable_text
|
||||
if readtext:
|
||||
string = "You read {C%s{n:\n %s" % (obj.key, readtext)
|
||||
|
|
@ -100,7 +100,7 @@ class CmdSetReadable(CmdSet):
|
|||
class Readable(TutorialObject):
|
||||
"""
|
||||
This object defines some attributes and defines a read method on itself.
|
||||
"""
|
||||
"""
|
||||
def at_object_creation(self):
|
||||
"Called when object is created"
|
||||
super(Readable, self).at_object_creation()
|
||||
|
|
@ -116,14 +116,14 @@ class Readable(TutorialObject):
|
|||
#
|
||||
# The climbable object works so that once climbed, it sets
|
||||
# a flag on the climber to show that it was climbed. A simple
|
||||
# command 'climb' handles the actual climbing.
|
||||
# command 'climb' handles the actual climbing.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class CmdClimb(Command):
|
||||
"""
|
||||
Usage:
|
||||
climb <object>
|
||||
Usage:
|
||||
climb <object>
|
||||
"""
|
||||
key = "climb"
|
||||
locks = "cmd:all()"
|
||||
|
|
@ -140,7 +140,7 @@ class CmdClimb(Command):
|
|||
return
|
||||
if obj != self.obj:
|
||||
self.caller.msg("Try as you might, you cannot climb that.")
|
||||
return
|
||||
return
|
||||
ostring = self.obj.db.climb_text
|
||||
if not ostring:
|
||||
ostring = "You climb %s. Having looked around, you climb down again." % self.obj.name
|
||||
|
|
@ -153,10 +153,10 @@ class CmdSetClimbable(CmdSet):
|
|||
"populate set"
|
||||
self.add(CmdClimb())
|
||||
|
||||
|
||||
|
||||
class Climbable(TutorialObject):
|
||||
"A climbable object."
|
||||
|
||||
|
||||
def at_object_creation(self):
|
||||
"Called at initial creation only"
|
||||
self.cmdset.add_default(CmdSetClimbable, permanent=True)
|
||||
|
|
@ -165,14 +165,14 @@ class Climbable(TutorialObject):
|
|||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Obelisk - a unique item
|
||||
# Obelisk - a unique item
|
||||
#
|
||||
# The Obelisk is an object with a modified return_appearance
|
||||
# method that causes it to look slightly different every
|
||||
# time one looks at it. Since what you actually see
|
||||
# is a part of a game puzzle, the act of looking also
|
||||
# method that causes it to look slightly different every
|
||||
# time one looks at it. Since what you actually see
|
||||
# is a part of a game puzzle, the act of looking also
|
||||
# stores a key attribute on the looking object for later
|
||||
# reference.
|
||||
# reference.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
|
|
@ -181,36 +181,36 @@ OBELISK_DESCS = ["You can briefly make out the image of {ba woman with a blue bi
|
|||
"For the briefest moment you make out an engraving of {ba regal woman wearing a crown{n.",
|
||||
"You think you can see the outline of {ba flaming shield{n in the stone.",
|
||||
"The surface for a moment seems to portray {ba woman fighting a beast{n."]
|
||||
|
||||
|
||||
class Obelisk(TutorialObject):
|
||||
"""
|
||||
This object changes its description randomly.
|
||||
"""
|
||||
|
||||
|
||||
def at_object_creation(self):
|
||||
"Called when object is created."
|
||||
super(Obelisk, self).at_object_creation()
|
||||
self.db.tutorial_info = "This object changes its desc randomly, and makes sure to remember which one you saw."
|
||||
# make sure this can never be picked up
|
||||
self.locks.add("get:false()")
|
||||
|
||||
|
||||
def return_appearance(self, caller):
|
||||
"Overload the default version of this hook."
|
||||
"Overload the default version of this hook."
|
||||
clueindex = random.randint(0, len(OBELISK_DESCS)-1)
|
||||
# set this description
|
||||
string = "The surface of the obelisk seem to waver, shift and writhe under your gaze, with "
|
||||
string += "different scenes and structures appearing whenever you look at it. "
|
||||
self.db.desc = string + OBELISK_DESCS[clueindex]
|
||||
# remember that this was the clue we got.
|
||||
caller.db.puzzle_clue = clueindex
|
||||
caller.db.puzzle_clue = clueindex
|
||||
# call the parent function as normal (this will use db.desc we just set)
|
||||
return super(Obelisk, self).return_appearance(caller)
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# LightSource
|
||||
# LightSource
|
||||
#
|
||||
# This object that emits light and can be
|
||||
# This object that emits light and can be
|
||||
# turned on or off. It must be carried to use and has only
|
||||
# a limited burn-time.
|
||||
# When burned out, it will remove itself from the carrying
|
||||
|
|
@ -228,7 +228,7 @@ class StateLightSourceOn(Script):
|
|||
self.key = "lightsourceBurn"
|
||||
self.desc = "Keeps lightsources burning."
|
||||
self.start_delay = True # only fire after self.interval s.
|
||||
self.repeats = 1 # only run once.
|
||||
self.repeats = 1 # only run once.
|
||||
self.persistent = True # survive a server reboot.
|
||||
|
||||
def at_start(self):
|
||||
|
|
@ -237,15 +237,15 @@ class StateLightSourceOn(Script):
|
|||
self.db.script_started = time.time()
|
||||
|
||||
def at_repeat(self):
|
||||
# this is only called when torch has burnt out
|
||||
# this is only called when torch has burnt out
|
||||
self.obj.db.burntime = -1
|
||||
self.obj.reset()
|
||||
|
||||
def at_stop(self):
|
||||
"""
|
||||
Since the user may also turn off the light
|
||||
Since the user may also turn off the light
|
||||
prematurely, this hook will store the current
|
||||
burntime.
|
||||
burntime.
|
||||
"""
|
||||
# calculate remaining burntime, if object is not
|
||||
# already deleted (because it burned out)
|
||||
|
|
@ -264,7 +264,7 @@ class StateLightSourceOn(Script):
|
|||
|
||||
class CmdLightSourceOn(Command):
|
||||
"""
|
||||
Switches on the lightsource.
|
||||
Switches on the lightsource.
|
||||
"""
|
||||
key = "on"
|
||||
aliases = ["switch on", "turn on", "light"]
|
||||
|
|
@ -273,16 +273,16 @@ class CmdLightSourceOn(Command):
|
|||
|
||||
def func(self):
|
||||
"Implements the command"
|
||||
|
||||
|
||||
if self.obj.db.is_active:
|
||||
self.caller.msg("%s is already burning." % self.obj.key)
|
||||
else:
|
||||
# set lightsource to active
|
||||
self.obj.db.is_active = True
|
||||
self.obj.db.is_active = True
|
||||
# activate the script to track burn-time.
|
||||
self.obj.scripts.add(StateLightSourceOn)
|
||||
self.obj.scripts.add(StateLightSourceOn)
|
||||
self.caller.msg("{gYou light {C%s.{n" % self.obj.key)
|
||||
self.caller.location.msg_contents("%s lights %s!" % (self.caller, self.obj.key), exclude=[self.caller])
|
||||
self.caller.location.msg_contents("%s lights %s!" % (self.caller, self.obj.key), exclude=[self.caller])
|
||||
# we run script validation on the room to make light/dark states tick.
|
||||
self.caller.location.scripts.validate()
|
||||
# look around
|
||||
|
|
@ -313,7 +313,7 @@ class CmdLightSourceOff(Command):
|
|||
self.caller.location.scripts.validate()
|
||||
self.caller.execute_cmd("look")
|
||||
# we run script validation on the room to make light/dark states tick.
|
||||
|
||||
|
||||
|
||||
class CmdSetLightSource(CmdSet):
|
||||
"CmdSet for the lightsource commands"
|
||||
|
|
@ -322,69 +322,69 @@ class CmdSetLightSource(CmdSet):
|
|||
"called at cmdset creation"
|
||||
self.add(CmdLightSourceOn())
|
||||
self.add(CmdLightSourceOff())
|
||||
|
||||
|
||||
class LightSource(TutorialObject):
|
||||
"""
|
||||
This implements a light source object.
|
||||
|
||||
When burned out, lightsource will be moved to its home - which by default is the
|
||||
location it was first created at.
|
||||
When burned out, lightsource will be moved to its home - which by default is the
|
||||
location it was first created at.
|
||||
"""
|
||||
def at_object_creation(self):
|
||||
"Called when object is first created."
|
||||
super(LightSource, self).at_object_creation()
|
||||
self.db.tutorial_info = "This object can be turned on off and has a timed script controlling it."
|
||||
self.db.is_active = False
|
||||
self.db.is_active = False
|
||||
self.db.burntime = 60*3 # 3 minutes
|
||||
self.db.desc = "A splinter of wood with remnants of resin on it, enough for burning."
|
||||
# add commands
|
||||
# add commands
|
||||
self.cmdset.add_default(CmdSetLightSource, permanent=True)
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Can be called by tutorial world runner, or by the script when the lightsource
|
||||
Can be called by tutorial world runner, or by the script when the lightsource
|
||||
has burned out.
|
||||
"""
|
||||
"""
|
||||
if self.db.burntime <= 0:
|
||||
# light burned out. Since the lightsources's "location" should be
|
||||
# light burned out. Since the lightsources's "location" should be
|
||||
# a character, notify them this way.
|
||||
try:
|
||||
loc = self.location.location
|
||||
except AttributeError:
|
||||
loc = self.location
|
||||
loc.msg_contents("{c%s{n {Rburns out.{n" % self.key)
|
||||
self.db.is_active = False
|
||||
self.db.is_active = False
|
||||
try:
|
||||
# validate in holders current room, if possible
|
||||
self.location.location.scripts.validate()
|
||||
# validate in holders current room, if possible
|
||||
self.location.location.scripts.validate()
|
||||
except AttributeError:
|
||||
# maybe it was dropped, try validating at current location.
|
||||
# maybe it was dropped, try validating at current location.
|
||||
try:
|
||||
self.location.scripts.validate()
|
||||
except AttributeError,e:
|
||||
pass
|
||||
pass
|
||||
self.delete()
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
# Crumbling wall - unique exit
|
||||
#
|
||||
# This implements a simple puzzle exit that needs to be
|
||||
# This implements a simple puzzle exit that needs to be
|
||||
# accessed with commands before one can get to traverse it.
|
||||
#
|
||||
# The puzzle is currently simply to move roots (that have
|
||||
# presumably covered the wall) aside until a button for a
|
||||
# secret door is revealed. The original position of the
|
||||
# roots blocks the button, so they have to be moved to a certain
|
||||
# position - when they have, the "press button" command
|
||||
# is made available and the Exit is made traversable.
|
||||
# The puzzle is currently simply to move roots (that have
|
||||
# presumably covered the wall) aside until a button for a
|
||||
# secret door is revealed. The original position of the
|
||||
# roots blocks the button, so they have to be moved to a certain
|
||||
# position - when they have, the "press button" command
|
||||
# is made available and the Exit is made traversable.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
# There are four roots - two horizontal and two vertically
|
||||
# running roots. Each can have three positions: top/middle/bottom
|
||||
# and left/middle/right respectively. There can be any number of
|
||||
# roots hanging through the middle position, but only one each
|
||||
# and left/middle/right respectively. There can be any number of
|
||||
# roots hanging through the middle position, but only one each
|
||||
# along the sides. The goal is to make the center position clear.
|
||||
# (yes, it's really as simple as it sounds, just move the roots
|
||||
# to each side to "win". This is just a tutorial, remember?)
|
||||
|
|
@ -396,35 +396,35 @@ class CmdShiftRoot(Command):
|
|||
shift blue root left/right
|
||||
shift red root left/right
|
||||
shift yellow root up/down
|
||||
shift green root up/down
|
||||
shift green root up/down
|
||||
|
||||
"""
|
||||
key = "shift"
|
||||
"""
|
||||
key = "shift"
|
||||
aliases = ["move"]
|
||||
# the locattr() lock looks for the attribute is_dark on the current room.
|
||||
locks = "cmd:not locattr(is_dark)"
|
||||
help_category = "TutorialWorld"
|
||||
|
||||
def parse(self):
|
||||
def parse(self):
|
||||
"custom parser; split input by spaces"
|
||||
self.arglist = self.args.strip().split()
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implement the command.
|
||||
Implement the command.
|
||||
blue/red - vertical roots
|
||||
yellow/green - horizontal roots
|
||||
"""
|
||||
|
||||
|
||||
if not self.arglist:
|
||||
self.caller.msg("What do you want to move, and in what direction?")
|
||||
return
|
||||
return
|
||||
if "root" in self.arglist:
|
||||
self.arglist.remove("root")
|
||||
# we accept arguments on the form <color> <direction>
|
||||
if not len(self.arglist) > 1:
|
||||
self.caller.msg("You must define which colour of root you want to move, and in which direction.")
|
||||
return
|
||||
return
|
||||
color = self.arglist[0].lower()
|
||||
direction = self.arglist[1].lower()
|
||||
# get current root positions dict
|
||||
|
|
@ -432,7 +432,7 @@ class CmdShiftRoot(Command):
|
|||
|
||||
if not color in root_pos:
|
||||
self.caller.msg("No such root to move.")
|
||||
return
|
||||
return
|
||||
|
||||
# first, vertical roots (red/blue) - can be moved left/right
|
||||
if color == "red":
|
||||
|
|
@ -496,11 +496,11 @@ class CmdShiftRoot(Command):
|
|||
self.caller.msg("The root with yellow flowers gets in the way and is pushed upwards.")
|
||||
else:
|
||||
self.caller.msg("You cannot move the root in that direction.")
|
||||
# store new position
|
||||
# store new position
|
||||
self.obj.db.root_pos = root_pos
|
||||
# check victory condition
|
||||
if root_pos.values().count(0) == 0: # no roots in middle position
|
||||
self.caller.db.crumbling_wall_found_button = True
|
||||
self.caller.db.crumbling_wall_found_button = True
|
||||
self.caller.msg("Holding aside the root you think you notice something behind it ...")
|
||||
|
||||
class CmdPressButton(Command):
|
||||
|
|
@ -511,19 +511,19 @@ class CmdPressButton(Command):
|
|||
aliases = ["press button", "button", "push", "push button"]
|
||||
locks = "cmd:attr(crumbling_wall_found_button) and not locattr(is_dark)" # only accessible if the button was found and there is light.
|
||||
help_category = "TutorialWorld"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Implements the command"
|
||||
|
||||
if self.caller.db.crumbling_wall_found_exit:
|
||||
# we already pushed the button
|
||||
self.caller.msg("The button folded away when the secret passage opened. You cannot push it again.")
|
||||
return
|
||||
|
||||
# pushing the button
|
||||
return
|
||||
|
||||
# pushing the button
|
||||
string = "You move your fingers over the suspicious depression, then gives it a "
|
||||
string += "decisive push. First nothing happens, then there is a rumble and a hidden "
|
||||
string += "{wpassage{n opens, dust and pebbles rumbling as part of the wall moves aside."
|
||||
string += "{wpassage{n opens, dust and pebbles rumbling as part of the wall moves aside."
|
||||
|
||||
# we are done - this will make the exit traversable!
|
||||
self.caller.db.crumbling_wall_found_exit = True
|
||||
|
|
@ -531,7 +531,7 @@ class CmdPressButton(Command):
|
|||
eloc = self.caller.search(self.obj.db.destination, global_search=True)
|
||||
if not eloc:
|
||||
self.caller.msg("The exit leads nowhere, there's just more stone behind it ...")
|
||||
return
|
||||
return
|
||||
self.obj.destination = eloc
|
||||
self.caller.msg(string)
|
||||
|
||||
|
|
@ -539,22 +539,22 @@ class CmdSetCrumblingWall(CmdSet):
|
|||
"Group the commands for crumblingWall"
|
||||
key = "crumblingwall_cmdset"
|
||||
def at_cmdset_creation(self):
|
||||
"called when object is first created."
|
||||
"called when object is first created."
|
||||
self.add(CmdShiftRoot())
|
||||
self.add(CmdPressButton())
|
||||
|
||||
|
||||
class CrumblingWall(TutorialObject, Exit):
|
||||
"""
|
||||
The CrumblingWall can be examined in various
|
||||
ways, but only if a lit light source is in the room. The traversal
|
||||
itself is blocked by a traverse: lock on the exit that only
|
||||
itself is blocked by a traverse: lock on the exit that only
|
||||
allows passage if a certain attribute is set on the trying
|
||||
player.
|
||||
|
||||
Important attribute
|
||||
destination - this property must be set to make this a valid exit
|
||||
whenever the button is pushed (this hides it as an exit
|
||||
until it actually is)
|
||||
whenever the button is pushed (this hides it as an exit
|
||||
until it actually is)
|
||||
"""
|
||||
def at_object_creation(self):
|
||||
"called when the object is first created."
|
||||
|
|
@ -567,17 +567,17 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
self.locks.add("cmd:not locattr(is_dark)")
|
||||
|
||||
self.db.tutorial_info = "This is an Exit with a conditional traverse-lock. Try to shift the roots around."
|
||||
# the lock is important for this exit; we only allow passage if we "found exit".
|
||||
# the lock is important for this exit; we only allow passage if we "found exit".
|
||||
self.locks.add("traverse:attr(crumbling_wall_found_exit)")
|
||||
# set cmdset
|
||||
self.cmdset.add(CmdSetCrumblingWall, permanent=True)
|
||||
|
||||
# starting root positions. H1/H2 are the horizontally hanging roots, V1/V2 the
|
||||
# vertically hanging ones. Each can have three positions: (-1, 0, 1) where
|
||||
# 0 means the middle position. yellow/green are horizontal roots and red/blue vertical.
|
||||
# all may have value 0, but never any other identical value.
|
||||
# 0 means the middle position. yellow/green are horizontal roots and red/blue vertical.
|
||||
# all may have value 0, but never any other identical value.
|
||||
self.db.root_pos = {"yellow":0, "green":0, "red":0, "blue":0}
|
||||
|
||||
|
||||
def _translate_position(self, root, ipos):
|
||||
"Translates the position into words"
|
||||
rootnames = {"red": "The {rreddish{n vertical-hanging root ",
|
||||
|
|
@ -595,10 +595,10 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
string = rootnames[root] + hpos[ipos]
|
||||
else:
|
||||
string = rootnames[root] + vpos[ipos]
|
||||
return string
|
||||
return string
|
||||
|
||||
def return_appearance(self, caller):
|
||||
"This is called when someone looks at the wall. We need to echo the current root positions."
|
||||
"This is called when someone looks at the wall. We need to echo the current root positions."
|
||||
if caller.db.crumbling_wall_found_button:
|
||||
string = "Having moved all the roots aside, you find that the center of the wall, "
|
||||
string += "previously hidden by the vegetation, hid a curious square depression. It was maybe once "
|
||||
|
|
@ -609,11 +609,11 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
string += "The roots (or whatever they are - some of them are covered in small non-descript flowers) "
|
||||
string += "crisscross the wall, making it hard to clearly see its stony surface.\n"
|
||||
for key, pos in self.db.root_pos.items():
|
||||
string += "\n" + self._translate_position(key, pos)
|
||||
self.db.desc = string
|
||||
string += "\n" + self._translate_position(key, pos)
|
||||
self.db.desc = string
|
||||
# call the parent to continue execution (will use desc we just set)
|
||||
return super(CrumblingWall, self).return_appearance(caller)
|
||||
|
||||
|
||||
def at_after_traverse(self, traverser, source_location):
|
||||
"This is called after we traversed this exit. Cleans up and resets the puzzle."
|
||||
del traverser.db.crumbling_wall_found_button
|
||||
|
|
@ -621,7 +621,7 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
self.reset()
|
||||
|
||||
def at_failed_traverse(self, traverser):
|
||||
"This is called if the player fails to pass the Exit."
|
||||
"This is called if the player fails to pass the Exit."
|
||||
traverser.msg("No matter how you try, you cannot force yourself through %s." % self.key)
|
||||
|
||||
def reset(self):
|
||||
|
|
@ -629,9 +629,9 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
self.location.msg_contents("The secret door closes abruptly, roots falling back into place.")
|
||||
for obj in self.location.contents:
|
||||
# clear eventual puzzle-solved attribues on everyone that didn't get out in time. They
|
||||
# have to try again.
|
||||
# have to try again.
|
||||
del obj.db.crumbling_wall_found_exit
|
||||
|
||||
|
||||
# Reset the roots with some random starting positions for the roots:
|
||||
start_pos = [{"yellow":1, "green":0, "red":0, "blue":0},
|
||||
{"yellow":0, "green":0, "red":0, "blue":0},
|
||||
|
|
@ -639,31 +639,31 @@ class CrumblingWall(TutorialObject, Exit):
|
|||
{"yellow":1, "green":0, "red":0, "blue":0},
|
||||
{"yellow":0, "green":0, "red":0, "blue":1}]
|
||||
self.db.root_pos = start_pos[random.randint(0, 4)]
|
||||
self.destination = None
|
||||
self.destination = None
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Weapon - object type
|
||||
#
|
||||
# A weapon is necessary in order to fight in the tutorial
|
||||
# world. A weapon (which here is assumed to be a bladed
|
||||
# world. A weapon (which here is assumed to be a bladed
|
||||
# melee weapon for close combat) has three commands,
|
||||
# stab, slash and defend. Weapons also have a property "magic"
|
||||
# to determine if they are usable against certain enemies.
|
||||
#
|
||||
# Since Characters don't have special skills in the tutorial,
|
||||
# we let the weapon itself determine how easy/hard it is
|
||||
# to hit with it, and how much damage it can do.
|
||||
#
|
||||
# to hit with it, and how much damage it can do.
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class CmdAttack(Command):
|
||||
"""
|
||||
Attack the enemy. Commands:
|
||||
Attack the enemy. Commands:
|
||||
|
||||
stab <enemy>
|
||||
slash <enemy>
|
||||
parry
|
||||
stab <enemy>
|
||||
slash <enemy>
|
||||
parry
|
||||
|
||||
stab - (thrust) makes a lot of damage but is harder to hit with.
|
||||
slash - is easier to land, but does not make as much damage.
|
||||
|
|
@ -672,7 +672,7 @@ class CmdAttack(Command):
|
|||
"""
|
||||
|
||||
# this is an example of implementing many commands as a single command class,
|
||||
# using the given command alias to separate between them.
|
||||
# using the given command alias to separate between them.
|
||||
|
||||
key = "attack"
|
||||
aliases = ["hit","kill", "fight", "thrust", "pierce", "stab", "slash", "chop", "parry", "defend"]
|
||||
|
|
@ -683,50 +683,50 @@ class CmdAttack(Command):
|
|||
"Implements the stab"
|
||||
|
||||
cmdstring = self.cmdstring
|
||||
|
||||
|
||||
|
||||
|
||||
if cmdstring in ("attack", "fight"):
|
||||
string = "How do you want to fight? Choose one of 'stab', 'slash' or 'defend'."
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
# parry mode
|
||||
if cmdstring in ("parry", "defend"):
|
||||
# parry mode
|
||||
if cmdstring in ("parry", "defend"):
|
||||
string = "You raise your weapon in a defensive pose, ready to block the next enemy attack."
|
||||
self.caller.msg(string)
|
||||
self.caller.db.combat_parry_mode = True
|
||||
self.caller.db.combat_parry_mode = True
|
||||
self.caller.location.msg_contents("%s takes a defensive stance" % self.caller, exclude=[self.caller])
|
||||
return
|
||||
return
|
||||
|
||||
if not self.args:
|
||||
self.caller.msg("Who do you attack?")
|
||||
return
|
||||
return
|
||||
target = self.caller.search(self.args.strip())
|
||||
if not target:
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
string = ""
|
||||
tstring = ""
|
||||
ostring = ""
|
||||
if cmdstring in ("thrust", "pierce", "stab"):
|
||||
if cmdstring in ("thrust", "pierce", "stab"):
|
||||
hit = float(self.obj.db.hit) * 0.7 # modified due to stab
|
||||
damage = self.obj.db.damage * 2 # modified due to stab
|
||||
string = "You stab with %s. " % self.obj.key
|
||||
tstring = "%s stabs at you with %s. " % (self.caller.key, self.obj.key)
|
||||
ostring = "%s stabs at %s with %s. " % (self.caller.key, target.key, self.obj.key)
|
||||
self.caller.db.combat_parry_mode = False
|
||||
self.caller.db.combat_parry_mode = False
|
||||
elif cmdstring in ("slash", "chop"):
|
||||
hit = float(self.obj.db.hit) # un modified due to slash
|
||||
damage = self.obj.db.damage # un modified due to slash
|
||||
damage = self.obj.db.damage # un modified due to slash
|
||||
string = "You slash with %s. " % self.obj.key
|
||||
tstring = "%s slash at you with %s. " % (self.caller.key, self.obj.key)
|
||||
ostring = "%s slash at %s with %s. " % (self.caller.key, target.key, self.obj.key)
|
||||
self.caller.db.combat_parry_mode = False
|
||||
self.caller.db.combat_parry_mode = False
|
||||
else:
|
||||
self.caller.msg("You fumble with your weapon, unable to choose an appropriate action...")
|
||||
self.caller.location.msg_contents("%s fumbles with their weapon." % self.obj.key)
|
||||
self.caller.db.combat_parry_mode = False
|
||||
return
|
||||
return
|
||||
|
||||
if target.db.combat_parry_mode:
|
||||
# target is defensive; even harder to hit!
|
||||
|
|
@ -737,17 +737,17 @@ class CmdAttack(Command):
|
|||
self.caller.msg(string + "{gIt's a hit!{n")
|
||||
target.msg(tstring + "{rIt's a hit!{n")
|
||||
self.caller.location.msg_contents(ostring + "It's a hit!", exclude=[target,self.caller])
|
||||
|
||||
|
||||
# call enemy hook
|
||||
if hasattr(target, "at_hit"):
|
||||
# should return True if target is defeated, False otherwise.
|
||||
return target.at_hit(self.obj, self.caller, damage)
|
||||
elif target.db.health:
|
||||
target.db.health -= damage
|
||||
target.db.health -= damage
|
||||
else:
|
||||
# sorry, impossible to fight this enemy ...
|
||||
self.caller.msg("The enemy seems unaffacted.")
|
||||
return False
|
||||
return False
|
||||
else:
|
||||
self.caller.msg(string + "{rYou miss.{n")
|
||||
target.msg(tstring + "{gThey miss you.{n")
|
||||
|
|
@ -775,9 +775,9 @@ class Weapon(TutorialObject):
|
|||
self.db.hit = 0.4 # hit chance
|
||||
self.db.parry = 0.8 # parry chance
|
||||
self.damage = 8.0
|
||||
self.magic = False
|
||||
self.magic = False
|
||||
self.cmdset.add_default(CmdSetWeapon, permanent=True)
|
||||
|
||||
|
||||
def reset(self):
|
||||
"When reset, the weapon is simply deleted, unless it has a place to return to."
|
||||
if self.location.has_player and self.home == self.location:
|
||||
|
|
@ -787,8 +787,8 @@ class Weapon(TutorialObject):
|
|||
self.location = self.home
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Weapon rack - spawns weapons
|
||||
#
|
||||
# Weapon rack - spawns weapons
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
|
|
@ -809,7 +809,7 @@ class CmdGetWeapon(Command):
|
|||
|
||||
rack_id = self.obj.db.rack_id
|
||||
if eval("self.caller.db.%s" % rack_id):
|
||||
# we don't allow to take more than one weapon from rack.
|
||||
# we don't allow to take more than one weapon from rack.
|
||||
self.caller.msg("%s has no more to offer." % self.obj.name)
|
||||
else:
|
||||
dmg, name, aliases, desc, magic = self.obj.randomize_type()
|
||||
|
|
@ -834,8 +834,8 @@ class CmdSetWeaponRack(CmdSet):
|
|||
key = "weaponrack_cmdset"
|
||||
mergemode = "Replace"
|
||||
def at_cmdset_creation(self):
|
||||
self.add(CmdGetWeapon())
|
||||
|
||||
self.add(CmdGetWeapon())
|
||||
|
||||
class WeaponRack(TutorialObject):
|
||||
"""
|
||||
This will spawn a new weapon for the player unless the player already has one from this rack.
|
||||
|
|
@ -852,7 +852,7 @@ class WeaponRack(TutorialObject):
|
|||
self.rack_id = "weaponrack_1"
|
||||
self.db.min_dmg = 1.0
|
||||
self.db.max_dmg = 4.0
|
||||
self.db.magic = False
|
||||
self.db.magic = False
|
||||
|
||||
def randomize_type(self):
|
||||
"""
|
||||
|
|
@ -867,26 +867,26 @@ class WeaponRack(TutorialObject):
|
|||
name = "Knife"
|
||||
desc = "A rusty kitchen knife. Better than nothing."
|
||||
elif dmg < 2.0:
|
||||
name = "Rusty dagger"
|
||||
name = "Rusty dagger"
|
||||
desc = "A double-edged dagger with nicked edge. It has a wooden handle."
|
||||
elif dmg < 3.0:
|
||||
name = "Sword"
|
||||
name = "Sword"
|
||||
desc = "A rusty shortsword. It has leather wrapped around the handle."
|
||||
elif dmg < 4.0:
|
||||
name = "Club"
|
||||
elif dmg < 4.0:
|
||||
name = "Club"
|
||||
desc = "A heavy wooden club with some rusty spikes in it."
|
||||
elif dmg < 5.0:
|
||||
name = "Ornate Longsword"
|
||||
name = "Ornate Longsword"
|
||||
aliases.extend(["longsword","ornate"])
|
||||
desc = "A fine longsword."
|
||||
elif dmg < 6.0:
|
||||
name = "Runeaxe"
|
||||
name = "Runeaxe"
|
||||
aliases.extend(["rune","axe"])
|
||||
desc = "A single-bladed axe, heavy but yet easy to use."
|
||||
elif dmg < 7.0:
|
||||
name = "Broadsword named Thruning"
|
||||
aliases.extend(["thruning","broadsword"])
|
||||
desc = "This heavy bladed weapon is marked with the name 'Thruning'. It is very powerful in skilled hands."
|
||||
desc = "This heavy bladed weapon is marked with the name 'Thruning'. It is very powerful in skilled hands."
|
||||
elif dmg < 8.0:
|
||||
name = "Silver Warhammer"
|
||||
aliases.append("warhammer")
|
||||
|
|
@ -901,8 +901,8 @@ class WeaponRack(TutorialObject):
|
|||
desc = "This massive sword is large as you are tall. Its metal shine with a bluish glow."
|
||||
else:
|
||||
name = "The Hawkblade"
|
||||
aliases.append("hawkblade")
|
||||
aliases.append("hawkblade")
|
||||
desc = "White surges of magical power runs up and down this runic blade. The hawks depicted on its hilt almost seems to have a life of their own."
|
||||
if dmg < 9 and magic:
|
||||
desc += "\nThe metal seems to glow faintly, as if imbued with more power than what is immediately apparent."
|
||||
desc += "\nThe metal seems to glow faintly, as if imbued with more power than what is immediately apparent."
|
||||
return dmg, name, aliases, desc, magic
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ class TeleportRoom(TutorialRoom):
|
|||
# passed the puzzle
|
||||
teleport_to = self.db.success_teleport_to # this is a room name
|
||||
|
||||
results = search_object(teleport_to, global_search=True)
|
||||
results = search_object(teleport_to)
|
||||
if not results or len(results) > 1:
|
||||
# we cannot move anywhere since no valid target was found.
|
||||
print "no valid teleport target for %s was found." % teleport_to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue