diff --git a/python/items/lockable_doors.py b/python/items/lockable_doors.py index c6fceba5a..37dc234d7 100644 --- a/python/items/lockable_doors.py +++ b/python/items/lockable_doors.py @@ -26,12 +26,17 @@ # # Note: using a DOOR (type 23) instead of a LOCKED_DOOR (type 20) doesn't seem to # work, since any key can remove the door - not the desired behaviour. +# +# If the lockable door has the correct 'trigger' hook (case for the previous archetypes), +# then the door can be picked, depending on the player's lockpicking level. +# Experience is awarded for the first successful pick only. Failures decrease the +# chance to succeed, and increase the chance of leaving traces. import Crossfire - -Crossfire.SetReturnValue(1) +import random def get_door(me, direction): + '''Find the first item in the specified direction''' map = me.Map x = me.X y = me.Y @@ -55,6 +60,7 @@ def get_door(me, direction): return ob def give_properties(who, lock): + '''Give properties from either the archetype or the other archetype.''' if lock == who.Archetype.Clone.Alive: arch = who.Archetype else: @@ -66,7 +72,16 @@ def give_properties(who, lock): who.Name = arch.Clone.Name who.Face = arch.Clone.Face +def check_picked(door, who): + '''Check if the lock was picked, and inform the player if this is the case.''' + if door.ReadKey('door_picked') == '1': + who.Write('You notice some suspicious traces on the lock.') + door.WriteKey('door_picked', '') + def handle_key(): + '''Handle applying a locking key.''' + Crossfire.SetReturnValue(1) + key = Crossfire.WhoAmI() who = Crossfire.WhoIsActivator() @@ -87,6 +102,7 @@ def handle_key(): else: who.Write('You unlock the %s'%(door.Name)) give_properties(door, 0) + check_picked(door, who) else: # door is unlocked, a key can lock if blank or matching if key.Slaying == '' or key.Slaying == None or key.Slaying == door.Slaying: @@ -95,7 +111,65 @@ def handle_key(): key.Name = key.Name + " (used)" who.Write('You lock the %s'%(door.Name)) give_properties(door, 1) + check_picked(door, who) else: who.Write("You can't use this %s on this %s"%(key.Name, door.Name)) -handle_key() +def get_attempts(door, who): + '''Get how many attempts to pick a lock a player did''' + s = door.ReadKey('attempts_' + who.Name) + if s == '': + return 0 + return int(s) + +def get_success_chance(door, who, level): + '''Return the chance of successfully picking the lock for the player''' + if door.ReadKey('was_picked_' + who.Name) != '': + return 100 + attempts = min(get_attempts(door, who), 5) + diff = level - door.Level - attempts + #who.Write('chance: %d'%(max(25, min(90, 50 + diff * 5)))) + return max(25, min(90, 50 + diff * 5)) + +def get_exp(door, who): + '''Return the experience for lockpicking the door''' + if door.ReadKey('was_picked_' + who.Name) != '': + return 0 + attempts = get_attempts(door, who) + #who.Write('exp: %d'%(round((door.Exp * (100. - min(100., attempts * 20.))) / 100.))) + return round((door.Exp * (100. - min(100., attempts * 20.))) / 100.) + +def handle_lockpick(): + '''Handle lockpicking a door.''' + Crossfire.SetReturnValue(1) + + door = Crossfire.WhoAmI() + who = Crossfire.WhoIsActivator() + + if who == None: + return + + if door.Alive == 0: + who.Write("This %s is unlocked."%(door.Name)) + return + + chance = get_success_chance(door, who, Crossfire.WhoIsOther().Level) + # chance to leave traces on the lock + if random.randint(0, 100) < 100 - chance: + door.WriteKey('door_picked', '1', 1) + + # attempt to unlock + if random.randint(0, 100) < chance: + who.Write('You successfully pick the lock.') + give_properties(door, 0) + who.AddExp(get_exp(door, who), Crossfire.WhoIsOther().Name) + door.WriteKey('was_picked_' + who.Name, '1', 1) + else: + who.Write('You fail to pick the lock.') + door.WriteKey('attempts_' + who.Name, str(get_attempts(door, who) + 1), 1) + +event = Crossfire.WhatIsEvent() +if event.Subtype == Crossfire.EventType.APPLY: + handle_key() +elif event.Subtype == Crossfire.EventType.TRIGGER: + handle_lockpick()