Crossfire Server, Trunk  1.75.0
roll-o-matic.py
Go to the documentation of this file.
1 # Script for the roll-o-matic.
2 # Idea courtesy Alex Schultz.
3 #
4 # Copyright 2007 Nicolas Weeger
5 # Released as GPL
6 #
7 # This script makes its item move following tiles, in direction specified by a player
8 
9 """
10 Using this script:
11 
12 1. Create a transport object in the map editor. Ensure that its type is actually TRANSPORT.
13 
14 2. Add Python events that trigger this script. Transports require at least two events:
15 
16  - event_time, which periodically calls this script to move the transport along
17 
18  - event_apply and/or event_say, to start and stop the transport
19 
20  In practice, each event has fields:
21 
22  title Python
23  slaying /python/items/roll-o-matic.py
24 
25  Optionally, add:
26 
27  name ship_mode
28 
29  Which makes roll-o-matic work for ships.
30 """
31 
32 import Crossfire
33 
34 key_direction = 'rom_dir'
35 key_follow = 'rom_follow'
36 
37 dir_x = [ 0, 0, 1, 1, 1, 0, -1, -1, -1 ]
38 dir_y = [ 0, -1, -1, 0, 1, 1, 1, 0, -1 ]
39 
40 ship_mode = False
41 
42 def is_floor(ob):
43  if ship_mode:
44  return ob.ArchName in {'sea_route', 'sea_route_2', 'sea_route_3', 'sea_route_4'}
45  else:
46  return ob.Floor == 1
47 
48 def find_floor(x, y):
49  """Find all objects satisfying is_floor() at the given location."""
50  obj = me.Map.ObjectAt(x, y)
51  while obj != None:
52  if is_floor(obj):
53  yield obj
54  obj = obj.Above
55 
57  obj = me.Map.ObjectAt(me.X, me.Y)
58  while obj != None:
59  if obj.Type == Crossfire.Type.PLAYER:
60  return obj
61  obj = obj.Above
62  return None
63 
64 def has_floor(x, y, name):
65  """Check whether one floor at the given location matches the given 'name'."""
66  for ob in find_floor(x, y):
67  if ob.Name == name:
68  return True
69  return False
70 
71 def abs_dir(d):
72  while d < 1:
73  d = d + 8
74  while d > 8:
75  d = d - 8
76  return d
77 
78 def stop():
79  me.WriteKey(key_direction, '', 1)
80  me.WriteKey(key_follow, '', 1)
81  me.Map.Print('The %s stops moving.'%me.Name)
82 
83 def try_move(check_directions, want_dir):
84  floor = me.ReadKey(key_follow)
85  x = me.X
86  y = me.Y
87  done = False
88  for check in check_directions:
89  d = abs_dir(want_dir + check)
90  if has_floor(x + dir_x[d], y + dir_y[d], floor):
91  # Next time, move in the direction we last moved in.
92  # This heuristic helps follow the roads better.
93  me.WriteKey(key_direction, str(d))
94  if me.Move(d) == 0:
95  continue
96 
97  if pl != None:
98  pl.Move(d)
99  done = True
100  break
101 
102  if not done:
103  stop()
104 
105 def do_shipwreck(me):
106  stop()
107 
109  want_dir = me.ReadKey(key_direction)
110  floor = me.ReadKey(key_follow)
111  if want_dir == '' or floor == '':
112  return
113 # me.Map.Print('roll')
114  pl = find_player()
115  want_dir = int(want_dir)
116  if ship_mode:
117  # For ship routes, check all candidate directions except the opposite-direction one.
118  check_directions = [0, 1, -1, 2, -2, 3, -3]
119 
120  curr_tile = me.Map.ObjectAt(me.X, me.Y)
121  while curr_tile != None:
122  if curr_tile.Name == 'shipwreck':
123  do_shipwreck(me)
124  return
125  curr_tile = curr_tile.Above
126  else:
127  # For roads, only check the routes that make progress in the right direction.
128  check_directions = [0, 1, -1]
129  try_move(check_directions, want_dir)
130 
131 def start_move(want_dir):
132  floors = list(find_floor(me.X, me.Y))
133  if len(floors) < 1:
134  return
135  floor = floors[0].Name
136 
137  if me.ReadKey(key_direction) == '':
138  me.Map.Print('The %s starts moving!' % me.Name)
139 
140  me.WriteKey(key_direction, str(want_dir), 1)
141  me.WriteKey(key_follow, floor, 1)
142 
144  msg = Crossfire.WhatIsMessage()
145  if msg == 'stop':
146  if me.ReadKey(key_direction) != '':
147  stop()
148  return
149 
150  want_dir = -1
151 
152  for d in Crossfire.DirectionName.keys():
153  if msg == Crossfire.DirectionName[d].lower():
154  want_dir = d
155  break
156 
157  if want_dir == -1:
158  return
159 
160  start_move(want_dir)
161 
163  if pl.Transport != None:
164  # Stop if already moving.
165  stop()
166  else:
167  # When applied, we don't know initial direction. Try to find one.
168  start_move(0)
169  try_move([0, 1, 2, 3, 4, 5, 6, 7], 0)
170  Crossfire.SetReturnValue(0)
171 
172 def do_handle():
173  if me.Map == None:
174  return
175 
176  if "ship_mode" in params:
177  global ship_mode
178  ship_mode = True
179 
180  Crossfire.SetReturnValue(1)
181 
182  if evt.Subtype == Crossfire.EventType.SAY:
183  handle_say()
184  elif evt.Subtype == Crossfire.EventType.APPLY:
185  handle_apply()
186  elif evt.Subtype == Crossfire.EventType.TIME:
187  handle_move()
188 
189 
190 evt = Crossfire.WhatIsEvent()
191 me = Crossfire.WhoAmI()
192 pl = Crossfire.WhoIsActivator()
193 params = Crossfire.ScriptParameters()
194 
195 do_handle()
roll-o-matic.handle_say
def handle_say()
Definition: roll-o-matic.py:143
roll-o-matic.is_floor
def is_floor(ob)
Definition: roll-o-matic.py:42
roll-o-matic.find_player
def find_player()
Definition: roll-o-matic.py:56
roll-o-matic.abs_dir
def abs_dir(d)
Definition: roll-o-matic.py:71
roll-o-matic.has_floor
def has_floor(x, y, name)
Definition: roll-o-matic.py:64
roll-o-matic.start_move
def start_move(want_dir)
Definition: roll-o-matic.py:131
roll-o-matic.do_shipwreck
def do_shipwreck(me)
Definition: roll-o-matic.py:105
roll-o-matic.try_move
def try_move(check_directions, want_dir)
Definition: roll-o-matic.py:83
roll-o-matic.find_floor
def find_floor(x, y)
Definition: roll-o-matic.py:48
roll-o-matic.stop
def stop()
Definition: roll-o-matic.py:78
roll-o-matic.do_handle
def do_handle()
Definition: roll-o-matic.py:172
roll-o-matic.handle_apply
def handle_apply()
Definition: roll-o-matic.py:162
list
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like doubleclick on crossfire32 dsw There are projects in your libcross lib and plugin_python You need to compile all Easiest way is to select the plugin_python ReleaseLog as active this will compile all others too Then in Visual C press< F7 > to compile If you don t have an appropriate compiler you can try to get the the VC copies the crossfire32 exe in the crossfire folder and the plugin_python dll in the crossfire share plugins folder we will remove it when we get time for it o Last showing lots of weird write to the Crossfire mailing list
Definition: INSTALL_WIN32.txt:50
roll-o-matic.handle_move
def handle_move()
Definition: roll-o-matic.py:108