maps/python/items/banquet.py

175 lines
5.1 KiB
Python

# Script for the Unforgettable Banquet of Lursendis item.
# Idea courtesy Yann Chachkoff.
#
# Copyright 2007 Nicolas Weeger
# Released as GPL
#
# This script will teleport the player to a food-filled map. It only works
# once a (ingame) day.
# Applying the tome while in the map will teleport the player back to his starting place.
# Book can only be applied when in player's inventory, so player can get back to the world.
#
# Map is generated by the script itself, and given a unique name to avoid collision.
#
# Player is replaced with a statue so the spot stays free during his trip.
# To avoid colliding with an existing map, created map will have a unique map.
# Everything in the map is randomly chosen.
import Crossfire
import random
import os.path
# map sizes
size_x = 15
size_y = 15
# what foods to put in the map
foods = [ 'fishfood', 'food', 'bag_popcorn', 'apple', 'cheeseburger', 'loaf', 'tomato', 'waybread', 'roast_bird', 'orange', 'leg_mutton' ]
# what floors can be used
floors = [ 'woodfloor', 'flagstone', 'dirtfloor' ]
# what walls can be used - only put the base name
walls = [ 'flagstone', 'dwall', 'timberwall', 'stwall' ]
# what to replace the player with. Should block all movement
replace_with = [ 'd_statue', 'statue', 'statue2' ]
def get_one(what):
'''Return a random choice in what, which should be an array.'''
return what[ random.randint( 1, len(what) ) - 1 ]
def return_to_bed():
'''Teleport player back to bed of reality. Only in emergency.'''
flags = 0
if (act.BedMap.find(Crossfire.PlayerDirectory()) != -1):
# Unique map
flags = 2
dest = Crossfire.ReadyMap(act.BedMap, flags)
if (dest == None):
# Ok, this is real bad. Let player handle the situation - worse case, call to DMs or WoR manually.
act.Message('The %s whines really loudly.'%l.Name)
return
act.Teleport(dest, act.BedX, act.BedY)
def do_back():
'''Teleport the player back to his starting point.'''
x = l.ReadKey('banquet_x')
y = l.ReadKey('banquet_y')
mn = l.ReadKey('banquet_map')
rw = l.ReadKey('banquet_rw')
l.WriteKey('banquet_x', '', 0)
l.WriteKey('banquet_y', '', 0)
l.WriteKey('banquet_map', '', 0)
l.WriteKey('banquet_rw', '', 0)
if x == '' or y == '' or mn == '':
# Logic error, but can't be helped - teleport player back to his bed of reality
act.Message('You feel a distorsion of reality!')
return_to_bed()
return
# find and remove statue in the map
dest = Crossfire.ReadyMap(mn)
if (dest == None):
# Random map, probably? Let the player teleport back him/herself.
act.Message('The %s whines something. You barely understand it can\'t take you back to your starting point.'%l.Name)
return_to_bed()
return
# Remove statue - let's assume it's found, or was removed due to map reset.
st = dest.ObjectAt(int(x), int(y))
while st != None:
if (st.ArchName != rw):
st = st.Above
continue
st.Remove()
break
act.Message('You feel a powerful force engulf you.')
act.Teleport(dest, int(x), int(y))
def do_banquet():
'''Teleports the player to the banquet map, if not used since one day. '''
now = str(Crossfire.GetTime()[0]) + '-' + str(Crossfire.GetTime()[1]) + '-' + str(Crossfire.GetTime()[2])
l = Crossfire.WhoAmI()
act = Crossfire.WhoIsActivator()
last = l.ReadKey('banquet_last')
if (last == now):
act.Message('You read the %s but nothing happens.'%l.Name)
return
l.WriteKey('banquet_last', now, 1)
# map generation
m = Crossfire.CreateMap(size_x, size_y)
m.Path = os.path.join(Crossfire.ScriptName(), Crossfire.WhoIsActivator().Name)
floor = get_one(floors)
# First, let's put the floors
for x in range(size_x):
for y in range(size_y):
fl = Crossfire.CreateObjectByName(floor)
fl.Teleport(m, x, y)
# Put walls.
wall = get_one(walls)
# top left
m.CreateObject(wall + '_2_2_2', 0, 0)
# top right
m.CreateObject(wall + '_2_2_3', size_x - 1, 0)
# bottom left
m.CreateObject(wall + '_2_2_1', 0, size_y - 1)
# bottom right
m.CreateObject(wall + '_2_2_4', size_x - 1, size_y - 1)
# top and bottom parts
for x in range(size_x - 2):
m.CreateObject(wall + '_2_1_2', x + 1, 0)
m.CreateObject(wall + '_2_1_2', x + 1, size_y - 1)
# left and right parts
for y in range(size_y - 2):
m.CreateObject(wall + '_2_1_1', 0, y + 1)
m.CreateObject(wall + '_2_1_1', size_x - 1, y + 1)
# Food itself
for x in range(size_x-2):
for y in range(size_y-2):
m.CreateObject(get_one(foods), x + 1, y + 1).GodGiven = 1
# Store player's current location
x = act.X
y = act.Y
im = act.Map
rw = get_one(replace_with)
l.WriteKey('banquet_x', str(x), 1)
l.WriteKey('banquet_y', str(y), 1)
l.WriteKey('banquet_map', im.Path, 1)
l.WriteKey('banquet_rw', rw, 1)
# Teleport
act.Message('You feel grabbed by some powerful force.')
act.Teleport(m, int(( size_x - 1 ) / 2), int((size_y - 1) / 2))
# Keep free spot by putting a statue
statue = im.CreateObject(rw, x, y)
statue.Name = '%s\'s statue'%act.Name
statue.Message = 'Gone eating.'
l = Crossfire.WhoAmI()
act = Crossfire.WhoIsActivator()
if l.Env != act:
act.Message('You try to open the %s, but it seems to flee from you.'%l.Name)
elif (act.Map.Path.find(Crossfire.ScriptName()) != -1):
do_back()
else:
do_banquet()
Crossfire.SetReturnValue(1)