1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<el:level xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://enigma-game.org/schema/level/1 level.xsd" xmlns:el="http://enigma-game.org/schema/level/1">
<el:protected>
<el:info el:type="library">
<el:identity el:title="" el:id="lib/andreas_ghosts"/>
<el:version el:score="1" el:release="1" el:revision="0" el:status="released"/>
<el:author el:name="Andreas Lochmann" el:email="" el:homepage=""/>
<el:copyright>Copyright © 2006 Andreas Lochmann</el:copyright>
<el:license el:type="GPL v2.0 or above" el:open="true"/>
<el:compatibility el:enigma="0.92">
</el:compatibility>
<el:modes el:easy="false" el:single="false" el:network="false"/>
<el:comments>
<el:code>Lua 5.1 and XML converted by Leveladministrators</el:code>
</el:comments>
<el:score el:easy="-" el:difficult="-"/>
</el:info>
<el:luamain><![CDATA[
-- andreas_ghosts, a lua-library for Enigma
--
-- Version 1/3
--
--
-- What is this?
--
-- With a "ghost" I mean an actor that's moving along predefined
-- ways ("rails") with possibly random behavior when choosing which
-- rail to follow. In terms of Esprit, these actors have been called
-- "spermbirds". Too avoid further confusion with future additions
-- of these very special actors (they have own images) to Enigma,
-- I call my version of them "ghosts". Take a look at the level
-- "Pac Marble" (andreas22) to see them doing their job.
--
--
-- Usage:
--
-- You have to set up four different kinds of objects:
--
-- (1) the ghosts themselves,
-- (2) the rails, which define the allowed ways for the ghosts,
-- (3) the timer-stone,
-- (4) if you use a level editor, correct the slope force.
--
-- (1) You can create a ghost via
--
-- ghosts_set_ghost(x,y,actor,rail,alg,attribs)
--
-- with x,y the position of the ghost, actor the type of actor
-- to be used (e.g. "ac-rotor" or "ac-blackball"), rail the number
-- of the rail the ghost might use, alg defining the algorithm to
-- be used (see below) and attribs a table of further attributes
-- for the actor. A typical example would be:
--
-- ghosts_set_ghost(12,13,"ac-top", 1, ghosts_direction_intelligent,
-- {range=0, force=5, gohome=FALSE})
--
-- You may use this as a parent for ant.lua, too:
--
-- actors["..."]=cell{parent={{ghosts_set_ghost,"ac-top",1,
-- ghosts_direction_intelligent,{range=0,force=5,gohome=FALSE}}}}
--
-- Remark 1: If you use a top or rotor, remember to set "gohome=FALSE",
-- otherwise the ghost will move unsteady or not at all.
-- Also reduce the range and/or force to sensible values.
-- If you use a marble, you should set "mouseforce=0".
-- Remark 2: Ghosts may not have arbitrary names! The name of a
-- ghost is determined as "ghost_X" with X the number of
-- the ghost, determined in the order of definition.
-- Remark 3: To each of the coordinates the value 0.5 will be added.
-- So, if you transform a set_actor-call, please subtract
-- 0.5 from each coordinate.
--
-- (2) Each ghost may move along paths, called rails. Several ghosts
-- may use the same rails, but each ghost only one rail; different
-- rails may cross. You can define a single floor tile as part of a
-- rail with
--
-- ghosts_set_rail(x,y,rail,floorkind)
--
-- with x,y the position of the floor, rail the rail-number that's
-- also used in the definition of the ghosts and floorkind the kind
-- of floor to be set at x,y. Instead of setting the floorkind with
-- ghosts_set_rail you can set it independently and use an empty
-- string '""' for floorkind, to suppress setting of a new floor.
-- You can use this as a parent for ant.lua, e.g.:
--
-- cells["..."]=cell{parent={{ghosts_set_rail,1,"fl-gray"}}}
--
-- To define a larger area as rail, you can use
--
-- ghosts_set_railarea(x1,y1,x2,y2,rail,floorkind)
--
-- which works analogously to ghosts_set_rail, with x1..x2, y1..y2
-- the rectangular area to be set as rail.
--
-- Remark 1: The movement of a ghost is done via flat gradients,
-- which alter the floor, while the old floor will be
-- reconstructed later. This might look strange when
-- another floor than "fl-metal" or "fl-gray" is used.
-- Remark 2: In the standard settings, rail-floors with walls on
-- them will be totally ignored as if they would not
-- belong to the rail at all. This way you can define
-- the whole area of a level as rail without having
-- to worry about walls, and the ghosts will ignore
-- movable stones instead of bump into them.
-- Yet, this behaviour can be unsatisfying, e.g. when
-- a ghost is expected to go through a grate, an open
-- door or a hollow stone. You can alter this by setting
--
-- ghosts_check_for_walls = 0
--
-- (or = 1 to switch it on again). Notice that a
-- ghost in this setting will bump into walls on its
-- way, which might look stupid. However, the ghost
-- will then reorient and search another way, so there
-- is no need to worry when switching this off.
-- Remark 3: Multiple rails have not been tested yet.
-- Keep lots of bug-spray in reach.
--
-- (3) You have to set up a timer stone which calls the function
-- ghosts_timercallback in appropriate intervals (e.g. 0.1 seconds).
-- You can do this with the function
--
-- ghosts_init(x,y)
--
-- with a nice position x,y for the timer-stone.
--
-- (4) The movements of the ghosts work via gradients and
-- thus need correctly set up slope forces. The library initially
-- sets it to 13, which works quite well. Editors like BlackBallEd
-- sometimes redefine this to other values. The code then needs
-- cleaning. You can also use
--
-- enigma.SlopeForce = ...
--
-- to slow the ghosts down or to speed them up. Bear in mind,
-- that too fast ghosts have problems in narrow labyrinths.
-- Yet, in an open area heightening the slope force can be
-- very sensible.
--
--
-- Moving algorithms:
--
-- In the current version of the library, there are four
-- algorithms that can be used in the definition of a ghost:
--
-- ghosts_direction_left : Always turn left at crossings
-- ghosts_direction_right : Always turn right at crossings
-- ghosts_direction_random : Choose ways randomly
-- ghosts_direction_intelligent : Choose rarely used ways
--
-- In the definition, you can also use "nil", then the
-- standard (ghosts_direction_intelligent) will be used.
-- But you might be interested to program an own algorithm
-- to decide the new directions by yourself. For this, you have
-- to define a function of the form
--
-- function my_own_algorithm(rail,posx,posy,oldx,oldy)
--
-- which takes the rail-number, the actual position and the old
-- position (which might be identical with the actual one). It
-- should return a single numerical value giving the direction:
--
-- 0 : No possible direction found
-- 1 : Go North (up)
-- 2 : Go South (down)
-- 3 : Go West (left)
-- 4 : Go East (right)
--
-- Then define your ghost using this function:
--
-- ghosts_set_ghost(12,13,"ac-rotor", 1, my_own_algorithm,
-- {range=0, force=5, gohome=FALSE})
--
-- Take a look at the four predefined functions to get a notion
-- of how to do this in a sensible way and which helper functions
-- you might find useful.
--
--
-- Global options:
--
-- There are four options that can be changed:
--
-- (a) ghosts_timerinterval (default 0.1)
-- Defines the callback interval used by ghosts_init.
-- (b) ghosts_waiting_constant (default 5)
-- When a ghost can't find a ways, it will repeat it after
-- this number of callback intervals. This number also is
-- used to give the ghost enough time to reach the next
-- adjacent floor tile before redefining its way.
-- (c) ghosts_check_for_walls (default 1, set to 0 for false)
-- Sets whether ghosts shall ignore walls or not.
-- See section (2), remark 2 for a detailed description.
-- (d) ghosts_marker_i_max (default 10000)
-- The intelligent direction algorithm uses counters to
-- count the number of times a floor tile has been visited.
-- To avoid an overflow of these counters, their maximum
-- is set to this constant, beyond which the intelligent
-- algorithm will turn into the random one. However, it's
-- improbable to reach this maximum during normal play.
--
-- For normal level-building purposes, only constant (c) should
-- be of interest.
--
--
-- Problem solving:
--
-- The ghost bumps into walls, moves unsteady, changes speed!
--
-- You probably forgot to set "gohome = FALSE".
--
-- The ghost bumps into walls, but moves with constant speed!
--
-- You probably switched ghosts_check_for_walls off, but didn't
-- remove the rail below static walls. The ghost thinks it can
-- go there, bumps into the wall and reorients -- very often.
--
-- The ghost doesn't move at all!
--
-- Have you set up the rail correctly, with the same rail number
-- as the ghost?
--
-- Have you set "gohome = FALSE"? In combination with a high
-- force-value this might also make the ghosts stop completely.
--
-- Possibly you use a rotor or top as ghost with activated range
-- and force. It then is attracted by your marble; stronger than
-- its gradient. Decrease the force or even better the range of
-- the ghost or turn the range off completely.
--
-- Maybe you renamed the ghost afterwards? This won't work.
-- Please use the predefined name of the ghost.
--
-- The ghost moves too fast or too slow!
--
-- Correct the slope force, c.f. section (4).
--
-- The ghost doesn't react on gradients/space/ice I put into the level!
--
-- The ghosts set up their own gradients they are surfing on,
-- and restore the old floor later. Thus there is no way to
-- make them react on any other floor; sorry.
--
-- I use marbles as ghosts and they react on the mouse movements!
--
-- If you don't want it this way, put "mouseforce = 0" into
-- the attribs.
--
-- The ghost moves somewhat... strange?
--
-- There are many things that can act on the ghosts, like magnets,
-- electricity, wormholes, interactions with other ghosts or actors
-- or the different attraction algorithms of tops and rotors that
-- can be accessed via the attacknearest-option. All of these aren't
-- tested and may lead to unpredictable behaviour of the ghosts.
-- Sorry if this disturbs your level idea.
--
--------------------------------------
-- Global constants and variables --
--------------------------------------
ghosts_timerinterval = 0.1
ghosts_waiting_constant = 5 -- corresponds to half a second
ghosts_check_for_walls = 1
ghosts_marker_i_max = 10000
enigma.SlopeForce = 13
ghosts_counter = 0
ghosts_rail = {}
ghosts_savedfloor = {}
ghosts_ghost_rail = {}
ghosts_ghost_x = {}
ghosts_ghost_y = {}
ghosts_waiting = {}
ghosts_possible = {}
ghosts_algorithm = {}
ghosts_marker_i = {}
ghosts_floor_x = {}
ghosts_floor_y = {}
-----------------------
-- Helper routines --
-----------------------
function ghosts_index(rail,x,y)
return tostring(rail)..";"..tostring(x)..";"..tostring(y)
end
function ghosts_adjacent(posx,posy,dir)
if dir == 0 then return posx, posy end
if dir == 1 then return posx, posy - 1 end
if dir == 2 then return posx, posy + 1 end
if dir == 3 then return posx - 1, posy end
if dir == 4 then return posx + 1, posy end
end
function ghosts_load_possible_directions(rail,posx,posy)
-- Test whether the four adjacent floors are allowed destinations
local j
for j=1,4 do
if ghosts_rail[ghosts_index(rail,ghosts_adjacent(posx,posy,j))] == 1 then
ghosts_possible[j] = 1
else
ghosts_possible[j] = 0
end
if ghosts_check_for_walls == 1 then
if enigma.GetStone(ghosts_adjacent(posx,posy,j)) ~= nil then
ghosts_possible[j] = 0
end
end
end
end
function ghosts_calculate_original_direction(posx,posy,oldx,oldy)
local originaldirection = 0
if (posx == oldx) and (posy == oldy - 1) then originaldirection = 2 end
if (posx == oldx) and (posy == oldy + 1) then originaldirection = 1 end
if (posy == oldy) and (posx == oldx - 1) then originaldirection = 4 end
if (posy == oldy) and (posx == oldx + 1) then originaldirection = 3 end
return originaldirection
end
function ghosts_turn_left(dir)
local newdir = 0
if dir == 1 then newdir = 4 end
if dir == 2 then newdir = 3 end
if dir == 3 then newdir = 1 end
if dir == 4 then newdir = 2 end
return newdir
end
function ghosts_turn_right(dir)
local newdir = 0
if dir == 1 then newdir = 3 end
if dir == 2 then newdir = 4 end
if dir == 3 then newdir = 2 end
if dir == 4 then newdir = 1 end
return newdir
end
function ghosts_increase_marker_i(rail,posx,posy)
local gcount = ghosts_marker_i[ghosts_index(rail,posx,posy)]
if gcount == nil then
ghosts_marker_i[ghosts_index(rail,posx,posy)] = 1
else
if gcount < ghosts_marker_i_max then
ghosts_marker_i[ghosts_index(rail,posx,posy)] = gcount + 1
end
end
end
function ghosts_floor_kind(actual, posx, posy, g)
local kind = actual
-- Is there any ghost who saved this floor apart from g?
for j = 1,ghosts_counter do
if (ghosts_floor_x[j] == posx) and (ghosts_floor_y[j] == posy) and (j ~= g) then
kind = ghosts_savedfloor[j]
end
end
if kind == nil then kind = actual end
return kind
end
function ghosts_gradient(dir)
--if dir == 1 then return "fl-gradient2" end
--if dir == 2 then return "fl-gradient1" end
--if dir == 3 then return "fl-gradient4" end
--if dir == 4 then return "fl-gradient3" end
return "fl-gradient"..tostring(dir+12)
end
---------------------------------
-- Several moving algorithms --
---------------------------------
-- 1 : Go North (up)
-- 2 : Go South (down)
-- 3 : Go West (left)
-- 4 : Go East (right)
function ghosts_direction_left(rail,posx,posy,oldx,oldy)
-- Calculate original direction (posx/posy -> oldx/oldy)
local originaldirection = ghosts_calculate_original_direction(posx,posy,oldx,oldy)
-- Load possible directions
ghosts_load_possible_directions(rail,posx,posy)
-- Are we still at the same position? Set origdir = random => dir = random
if (posx == oldx) and (posy == oldy) then
originaldirection = random(1,4)
end
-- Turn left till there is a possible way
local dir = ghosts_turn_left(originaldirection)
local j
for j = 1,3 do
if ghosts_possible[dir] ~= 1 then
dir = ghosts_turn_left(dir)
end
end
-- Maybe there is no way out?
if (dir == originaldirection) and (ghosts_possible[dir] ~= 1) then
dir = 0
end
return dir
end
function ghosts_direction_right(rail,posx,posy,oldx,oldy)
-- Calculate original direction (posx/posy -> oldx/oldy)
local originaldirection = ghosts_calculate_original_direction(posx,posy,oldx,oldy)
-- Load possible directions
ghosts_load_possible_directions(rail,posx,posy)
-- Are we still at the same position? -> dir = random
if (posx == oldx) and (posy == oldy) then
originaldirection = random(1,4)
end
-- Turn left till there is a possible way
local dir = ghosts_turn_right(originaldirection)
local j
for j = 1,3 do
if ghosts_possible[dir] ~= 1 then
dir = ghosts_turn_right(dir)
end
end
-- Maybe there is no way out?
if (dir == originaldirection) and (ghosts_possible[dir] ~= 1) then
dir = 0
end
return dir
end
function ghosts_direction_random(rail,posx,posy,oldx,oldy)
-- Calculate original direction (posx/posy -> oldx/oldy)
local originaldirection = ghosts_calculate_original_direction(posx,posy,oldx,oldy)
-- Load possible directions
ghosts_load_possible_directions(rail,posx,posy)
-- Choose one of them at random
local direction = 0
local j
for j=1,100 do
-- Try to find a good direction 100 times, then give up.
if direction == 0 then
direction = random(1,4)
if ghosts_possible[direction] ~= 1 then
direction = 0
end
if direction == originaldirection then
direction = 0
end
end
end
return direction
end
function ghosts_direction_intelligent(rail,posx,posy,oldx,oldy)
-- Calculate original direction (posx/posy -> oldx/oldy)
local originaldirection = ghosts_calculate_original_direction(posx,posy,oldx,oldy)
-- Load possible directions with counters
ghosts_load_possible_directions(rail, posx, posy)
-- Save the corresponding markers in ghosts_possible
local j
local m
for j=1,4 do
m = ghosts_marker_i[ghosts_index(rail,ghosts_adjacent(posx,posy,j))]
if m == nil then
ghosts_marker_i[ghosts_index(rail,ghosts_adjacent(posx,posy,j))] = 1
m = 1
end
if ghosts_possible[j] > 0 then
ghosts_possible[j] = m
end
end
-- Remove directions with highest counters and original direction
if originaldirection > 0 then
ghosts_possible[originaldirection] = 0
end
local min = 0
for j = 1,4 do
if (min == 0) or ((min > ghosts_possible[j]) and (ghosts_possible[j] > 0))
then min = ghosts_possible[j] end
end
for j = 1,4 do
if min < ghosts_possible[j] then ghosts_possible[j] = 0 end
end
-- Choose one of the (hopefully) remaining directions at random
local direction = 0
for j=1,100 do
-- Like in the random algorithm:
if direction == 0 then
direction = random(1,4)
if ghosts_possible[direction] == 0 then
direction = 0
end
if direction == originaldirection then
direction = 0
end
end
end
return direction
end
-------------------------------
-- Timer callback function --
-------------------------------
function ghosts_timercallback()
if ghosts_counter > 0 then
local g
for g = 1, ghosts_counter do
local myactor = enigma.GetNamedObject("ghost_"..tostring(g))
if myactor ~= nil then
local posx, posy = enigma.GetPos(myactor)
local rail = ghosts_ghost_rail[g]
local oldx = ghosts_ghost_x[g]
local oldy = ghosts_ghost_y[g]
-- Are we still at the same position?
if (oldx == posx) and (oldy == posy) then
-- Should we wait some more time?
if ghosts_waiting[g] > 0 then
-- Wait some more...
ghosts_waiting[g] = ghosts_waiting[g] - 1
end
-- If we waited a too long time, increase the marker.
-- We'll also delete the original direction now, but
-- create a new gradient later.
if ghosts_waiting[g] == 0 then
ghosts_increase_marker_i(rail, posx, posy)
ghosts_ghost_x[g] = posx
ghosts_ghost_y[g] = posy
end
else
-- Create a new gradient without further waiting!
ghosts_waiting[g] = 0
-- And increase the local counter.
ghosts_increase_marker_i(rail, posx, posy)
end
-- Shall we restore the old floor?
local oldfloorx = ghosts_floor_x[g]
local oldfloory = ghosts_floor_y[g]
if (oldfloorx ~= posx) or (oldfloory ~= posy) then
-- Restore the old floor:
if ghosts_savedfloor[g] == "" then
ghosts_savedfloor[g] = "fl-normal"
end
-- Why not oldx/oldy? Because the actor could have
-- been bumped onto another field - this would shuffle
-- the floor-tiles!
set_floor(ghosts_savedfloor[g], oldfloorx, oldfloory)
end
-- Should we create some gradient where we are?
local dir = 0
if ghosts_waiting[g] == 0 then
-- Calculate new direction
if ghosts_rail[ghosts_index(rail,posx,posy)] == nil then
-- Oh, that's not good: the actor lost his way.
-- Maybe we can get it back onto the rail where it came from?
if ghosts_rail[ghosts_index(rail,oldx,oldy)] ~= nil then
dir = ghosts_calculate_original_direction(posx,posy,oldx,oldy)
end
if dir == 0 then
-- Last chance!
dir = ghosts_direction_random(rail,posx,posy,oldx,oldy)
end
if dir == 0 then
-- No way back? Then just deactivate it:
ghosts_waiting[g] = -1
end
else
dir = ghosts_algorithm[g](rail, posx, posy, oldx, oldy)
end
-- Any good idea? Then draw the gradient!
if dir ~= 0 then
local newfloor = ghosts_gradient(dir)
if (posx ~= oldfloorx) or (posy ~= oldfloory)
or (ghosts_savedfloor[g] == "") then
local myfloor = enigma.GetFloor(posx,posy)
if myfloor ~= nil then
-- Save the old floor kind.
-- But take care: There might already be a ghost
-- here, who changed the floor kind!
ghosts_savedfloor[g] = ghosts_floor_kind(enigma.GetKind(myfloor),posx,posy,g)
ghosts_floor_x[g] = posx
ghosts_floor_y[g] = posy
end
end
set_floor(newfloor,posx,posy)
ghosts_ghost_x[g] = posx
ghosts_ghost_y[g] = posy
ghosts_waiting[g] = ghosts_waiting_constant
else
-- No direction? Propably a dead-end. Wait some time
-- and forget where you came from.
ghosts_ghost_x[g] = posx
ghosts_ghost_y[g] = posy
ghosts_waiting[g] = ghosts_waiting_constant
end
end
end
end
end
end
-------------------------------------------------
-- Initialization, Setup and ant.lua-parents --
-------------------------------------------------
function ghosts_init(x,y)
set_stone("st-timer", x, y, {interval = ghosts_timerinterval,
action = "callback", target = "ghosts_timercallback"})
end
function ghosts_set_ghost(x,y,actor,rail,alg,attribs) -- Sets up a ghost
if alg == nil then alg = ghosts_direction_intelligent end
ghosts_counter = ghosts_counter + 1
local n = "ghost_"..tostring(ghosts_counter)
ghosts_ghost_rail[ghosts_counter] = rail
ghosts_ghost_x[ghosts_counter] = x
ghosts_ghost_y[ghosts_counter] = y
ghosts_waiting[ghosts_counter] = 0
ghosts_savedfloor[ghosts_counter] = ""
ghosts_algorithm[ghosts_counter] = alg
local newghost = set_actor(actor,x+0.5,y+0.5,{name=n})
set_attribs(newghost,attribs)
if GetAttrib(newghost,"name") ~= n then
error("Ghosts may not have arbitrary names!")
end
end
function ghosts_set_rail(x,y,rail,floorkind) -- This is a parent for a ghost-rail
if rail == "" then rail = 0 end
ghosts_rail[ghosts_index(rail,x,y)] = 1
if floorkind ~= "" then
set_floor(floorkind, x, y)
end
end
function ghosts_set_railarea(x1,y1,x2,y2,rail,floorkind)
local i,j
for i=x1,x2 do
for j=y1,y2 do
ghosts_set_rail(i,j,rail,floorkind)
end
end
end
]]></el:luamain>
<el:i18n>
</el:i18n>
</el:protected>
</el:level>
|