mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
820 lines
25 KiB
Text
820 lines
25 KiB
Text
Script & Config Changes for Editable Maps
|
|
9/10/02
|
|
Note the following changes and additions to support editable maps and course following boat functionality
|
|
(based on an 094 distro installation)
|
|
----
|
|
0.
|
|
New property for itemdesc.cfg Map{} entries: Editable, which defaults to 0
|
|
This determines if the user can plot points on the map gump. Note you can still edit the map
|
|
via the script methods listed under item 4.
|
|
|
|
1.
|
|
decodeMap.src, CreateTreasureMap:
|
|
var map := CreateItemInBackpack( who, GetObjtypeByName("map_nonedit"), 1 );
|
|
and at the end of SetTreasureCoords:
|
|
map.AppendPin(x,y);
|
|
|
|
2.
|
|
/pkg/skills/cartography/itemdesc.cfg
|
|
add:
|
|
Map 0x641E
|
|
{
|
|
Name map_nonedit
|
|
Desc Blank Map
|
|
Graphic 0x14EB
|
|
VendorSellsFor 10
|
|
VendorBuysFor 5
|
|
Editable 0
|
|
}
|
|
all the other entries add:
|
|
Editable 1
|
|
to, except for "rolledmap" and "rolledmap2"
|
|
|
|
3.
|
|
/pkg/items/treasuremap/itemdesc.cfg
|
|
add to all:
|
|
Editable 0
|
|
|
|
4.
|
|
New script methods for map obejcts:
|
|
GetPins(): returns an array of structs with .x and .y members for each pin point.
|
|
InsertPin( index, x, y ): inserts a pin with the passed x,y before the passed index. Valid range 0 to n-1
|
|
AppendPin( x, y ): appends a pin to the end of the course with the passed x,y
|
|
ErasePin( index ): erases the pin at the passed index (valid 0 to n-1), and shifts pins down.
|
|
isa(): returns true if the object is a map object
|
|
|
|
5.
|
|
Tillerman course follow functionality: in this boat.src (edit from the 094 distro)
|
|
////////////////
|
|
// boat.src
|
|
//
|
|
// control script for boats
|
|
//
|
|
// Header replaced by Racalac 9/15/02
|
|
//
|
|
// Todo/Fix: Course nav needs the "goto #" command implimented.
|
|
// Tillerman string recognition causes boat to pause
|
|
////////////////
|
|
|
|
use os;
|
|
use uo;
|
|
use util;
|
|
use boat;
|
|
use math;
|
|
|
|
include "include/eventID";
|
|
include "include/sysEvent";
|
|
include "include/myUtil";
|
|
include "include/client";
|
|
include "include/yesNo";
|
|
include "include/math";
|
|
include "util/key";
|
|
include "plankUtil";
|
|
|
|
const STATE_STATIONARY := 0;
|
|
const STATE_MOVING := 1;
|
|
const STATE_DRIFTING := 2;
|
|
const STATE_FOLLOWING_COURSE := 3;
|
|
const DELAY_DRIFTING := 15000;
|
|
|
|
const NEGONE := -1;
|
|
const ZERO := 0;
|
|
const POSONE := 1;
|
|
|
|
var state := STATE_STATIONARY;
|
|
var relative_direction;
|
|
var ms_delay_between_moves := 200;
|
|
var boat;
|
|
var tillerman;
|
|
var owner := GetObjProperty(boat.hold,"owner");
|
|
var decay := GetObjProperty(boat.tillerman, "decay");
|
|
var first_move_toward_waypoint := 1;
|
|
|
|
program autostart_boat(param)
|
|
boat := param;
|
|
if(!boat)
|
|
syslog( "[ERROR] [boat.src] Boat script running, but boat not found!" );
|
|
return;
|
|
endif
|
|
tillerman := boat.tillerman;
|
|
if(!tillerman)
|
|
syslog( "[ERROR] [boat.src] No tillerman for boat at: " +(boat.x-1) +","+ boat.y +","+ boat.z + "; destroying the boat..." );
|
|
DestroyMulti(boat);
|
|
return;
|
|
endif
|
|
EnableEvents(SYSEVENT_SPEECH, 15);
|
|
RegisterForSpeechEvents(tillerman, 15);
|
|
var nextencounter := ReadGameClock()+(RandomInt(120) + 120);
|
|
var nextsound := ReadGameClock()+5;
|
|
var driftcounter := 1;
|
|
//set_critical(1);
|
|
var x,y;
|
|
while(boat)
|
|
if(GetObjProperty(boat.hold, "#speed"))
|
|
state := STATE_MOVING;
|
|
ms_delay_between_moves := GetObjProperty(boat.hold, "#speed");
|
|
relative_direction := GetObjProperty(boat.hold, "#relativedir");
|
|
eraseobjproperty(boat.hold, "#speed");
|
|
eraseobjproperty(boat.hold, "#relativedir");
|
|
endif
|
|
decay := getobjproperty(boat.tillerman,"decay");
|
|
if((decay) and(!getobjproperty(tillerman,"nodecay")))
|
|
if(ReadGameClock() > decay)
|
|
PrintTextAbove(tillerman, "Arrrrrgh! She's going down, Captain! Abandon ship!");
|
|
sleep(4);
|
|
foreach item in EnumerateItemsInContainer( boat.hold )
|
|
DestroyItem(item);
|
|
endforeach
|
|
foreach mob in(boat.items)
|
|
DestroyItem(mob);
|
|
endforeach
|
|
foreach mob in(boat.mobiles)
|
|
MoveCharacterToLocation(mob, 1487, 1869, 0, MOVECHAR_FORCELOCATION );
|
|
SendSysMessage(mob, "Your ship, badly in need of maintenance, sinks beneath the waves!");
|
|
SendSysMessage(mob, "You awake on a distant shore...");
|
|
endforeach
|
|
if(boat.has_offline_mobiles)
|
|
foreach mob in(boat.offline_mobiles)
|
|
MoveCharacterToLocation(mob, 1487, 1869, 0, MOVECHAR_FORCELOCATION );
|
|
endforeach
|
|
endif
|
|
DestroyMulti(boat);
|
|
endif
|
|
endif
|
|
case(state)
|
|
STATE_MOVING: if(ReadGameClock() > nextsound)
|
|
PlayBoatSounds();
|
|
nextsound := ReadGameClock()+5;
|
|
endif
|
|
x := boat.x;
|
|
y := boat.y;
|
|
MoveBoatRelative(boat, relative_direction);
|
|
if(boat.x = 6 or boat.x = 5097 or boat.y = 6 or boat.y = 4089)
|
|
WorldWrap();
|
|
endif
|
|
if((x == boat.x) &&(y == boat.y))
|
|
ms_delay_between_moves := 1000;
|
|
state := STATE_DRIFTING;
|
|
PrintTextAbove(tillerman, "Aaargh! We've stopped!");
|
|
//SmackEveryone();
|
|
endif
|
|
sleepms(ms_delay_between_moves);
|
|
if(ReadGameClock() > nextencounter)
|
|
DoEncounter();
|
|
nextencounter := ReadGameClock()+120;
|
|
endif
|
|
while(events_waiting())
|
|
process_event(wait_for_event(0));
|
|
endwhile
|
|
STATE_DRIFTING: if(ReadGameClock() > nextsound)
|
|
PlayBoatSounds();
|
|
nextsound := ReadGameClock()+5;
|
|
endif
|
|
if(driftcounter > 15)
|
|
MoveBoatRelative(boat, RandomInt(8));
|
|
driftcounter := 1;
|
|
else
|
|
driftcounter := driftcounter + 1;
|
|
endif
|
|
sleepms(1000);
|
|
while(events_waiting())
|
|
process_event(wait_for_event(0));
|
|
endwhile
|
|
STATE_STATIONARY: var ev := wait_for_event(120);
|
|
if(ev)
|
|
process_event(ev);
|
|
endif
|
|
STATE_FOLLOWING_COURSE:
|
|
x := boat.x;
|
|
y := boat.y;
|
|
BoatFollowCourse(boat);
|
|
|
|
sleepms(ms_delay_between_moves);
|
|
while(events_waiting())
|
|
process_event(wait_for_event(0));
|
|
endwhile
|
|
endcase
|
|
if(ReadGameClock() > nextencounter)
|
|
checkres();
|
|
nextencounter := ReadGameClock()+120;
|
|
endif
|
|
endwhile
|
|
endprogram
|
|
|
|
function handle_speech(event)
|
|
var text := lower(event.text);
|
|
if(text["drift"] || text["raise anchor"])
|
|
ms_delay_between_moves := 1000;
|
|
state := STATE_DRIFTING;
|
|
elseif(text["forward"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
state := STATE_MOVING;
|
|
if(text["left"])
|
|
relative_direction := 7;
|
|
elseif(text["right"])
|
|
relative_direction := 1;
|
|
else
|
|
relative_direction := 0;
|
|
endif
|
|
endif
|
|
elseif(text["back"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
state := STATE_MOVING;
|
|
if(text["left"])
|
|
relative_direction := 5;
|
|
elseif(text["right"])
|
|
relative_direction := 3;
|
|
else
|
|
relative_direction := 4;
|
|
endif
|
|
endif
|
|
elseif(text["stop"] || text["furl sail"] || text["furl"])
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
ms_delay_between_moves := 1000;
|
|
state := STATE_DRIFTING;
|
|
elseif(text["drop anchor"])
|
|
PrintTextAbove(tillerman, "Aye Aye Captain! Anchor Dropped.");
|
|
ms_delay_between_moves := 1000;
|
|
state := STATE_STATIONARY;
|
|
elseif(text["turn right"] || text["starboard"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
TurnBoat(boat, 1);
|
|
endif
|
|
elseif(text["right"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
state := STATE_MOVING;
|
|
relative_direction := 2;
|
|
endif
|
|
elseif(text["turn left"] || text["port"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
TurnBoat(boat, 3);
|
|
endif
|
|
elseif(text["left"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain!");
|
|
state := STATE_MOVING;
|
|
relative_direction := 6;
|
|
endif
|
|
elseif(text["come about"] || text["turn around"])
|
|
if(state = STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "The Anchor Is Down Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Aye Aye Captain! Coming About.");
|
|
TurnBoat(boat, 2);
|
|
sleep(1);
|
|
endif
|
|
/*NEW MAP COURSE COMMANDS*/
|
|
elseif(text["set course"])
|
|
PrintTextAbove(tillerman, "Select a map for me to follow.");
|
|
var map := Target(event.source);
|
|
if(!map.isa(POLCLASS_MAP))
|
|
PrintTextAbove(tillerman, "Are ye dense? I need a map!");
|
|
else
|
|
SetObjProperty(tillerman, "course", map.GetPins());
|
|
SetObjProperty(tillerman, "nextwaypoint", 1);
|
|
PrintTextAbove(tillerman, "Arr, course plotted.");
|
|
endif
|
|
elseif(text["clear course"])
|
|
PrintTextAbove(tillerman, "Arr, course cleared Cap'n.");
|
|
EraseObjProperty(tillerman, "course");
|
|
EraseObjProperty(tillerman, "nextwaypoint");
|
|
elseif(text["nav"])
|
|
if(state != STATE_FOLLOWING_COURSE)
|
|
PrintTextAbove(tillerman, "We are not currently following a course.");
|
|
else
|
|
PrintTextAbove(tillerman, "We are following our course.");
|
|
PrintTextAbove(tillerman, "The next waypoint is #" + GetObjProperty(tillerman,"nextwaypoint"));
|
|
endif
|
|
elseif(text["start"])
|
|
if( (GetObjProperty(tillerman,"course")==error) || (GetObjProperty(tillerman,"nextwaypoint")==error))
|
|
PrintTextAbove(tillerman,"Arr, set course first Cap'n.");
|
|
else
|
|
state := STATE_FOLLOWING_COURSE;
|
|
SetObjProperty(tillerman, "nextwaypoint", 1);
|
|
PrintTextAbove(tillerman,"Aye, sailing to first waypoint.");
|
|
endif
|
|
elseif(text["continue"])
|
|
if( (GetObjProperty(tillerman,"course")==error) || (GetObjProperty(tillerman,"nextwaypoint")==error))
|
|
PrintTextAbove(tillerman,"Arr, set course first Cap'n.");
|
|
else
|
|
state := STATE_FOLLOWING_COURSE;
|
|
PrintTextAbove(tillerman,"Aye, moving on.");
|
|
endif
|
|
endif
|
|
/*END NEW MAP COURSE COMMANDS*/
|
|
if(text["full"])
|
|
if(state != STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "Aye Aye Captain! Full Speed Ahead.");
|
|
ms_delay_between_moves := 100;
|
|
endif
|
|
elseif(text["slow"])
|
|
if(state != STATE_STATIONARY)
|
|
PrintTextAbove(tillerman, "Aye Aye Captain! ");
|
|
ms_delay_between_moves := 1000;
|
|
endif
|
|
endif
|
|
|
|
sleep(1);
|
|
if(text["one"])
|
|
if(state != STATE_STATIONARY)
|
|
MoveBoatRelative(boat, relative_direction);
|
|
state := STATE_STATIONARY;
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function process_event(event)
|
|
if(event.type == SYSEVENT_SPEECH)
|
|
if(CanCommandMe(event.source))
|
|
var text := lower(event.text);
|
|
if(text["drydock"])
|
|
PrintTextAbove(tillerman, "Aye Aye Captain! Docking.");
|
|
drydock(event);
|
|
sleep(1);
|
|
elseif(text["status"])
|
|
decay := GetObjProperty(boat.tillerman, "decay");
|
|
if((decay - ReadGameClock() ) > 861000 )
|
|
PrintTextAbove( tillerman, "Arrh, the ship's in excellent shape! She's a fine vessel indeed, Captain!" );
|
|
elseif((decay - ReadGameClock() ) > 604800 )
|
|
PrintTextAbove( tillerman, "She's slightly worn, Captain.");
|
|
elseif((decay - ReadGameClock() ) > 259200 )
|
|
PrintTextAbove(tillerman, "She's fairly worn, Captain.");
|
|
elseif((decay - ReadGameClock() ) > 86400 )
|
|
PrintTextAbove(tillerman, "Arrr, she's greatly worn and in dire need of repair, Captain!");
|
|
else
|
|
PrintTextAbove(tillerman, "Arrr, she's going to sink within the day if she don't get repairs soon, Captain!");
|
|
endif
|
|
else
|
|
handle_speech(event);
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function CanCommandMe(who)
|
|
owner := GetObjProperty(boat.tillerman, "owner");
|
|
if(who.serial == owner)
|
|
return 1;
|
|
else
|
|
var packkey;
|
|
var lokid := GetObjProperty(boat.tillerman, "lockid");
|
|
foreach thing in EnumerateItemsInContainer(who.backpack)
|
|
if(GetObjProperty(thing, "lockid") = lokid)
|
|
packkey := 1;
|
|
break;
|
|
endif
|
|
endforeach
|
|
if(packkey = 1)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function DoEncounter()
|
|
foreach who in ListMobilesNearLocationEx(boat.x, boat.y, GetMapInfo(boat.x, boat.y).z, 4, LISTEX_FLAG_GHOST)
|
|
if(YesNo(who,"Ressurect?"))
|
|
PlaySoundEffect(who, SFX_SPELL_RESSURECTION);
|
|
PlaySoundEffect(who, SFX_SPELL_RESSURECTION);
|
|
Resurrect(who);
|
|
endif
|
|
endforeach
|
|
var who :=(boat.mobiles);
|
|
who := who[1];
|
|
if(!who)
|
|
return;
|
|
endif
|
|
var x;
|
|
var y;
|
|
var z;
|
|
x := RandomInt(15)-5;
|
|
y := RandomInt(15)-5;
|
|
x := x + boat.x;
|
|
y := y + boat.y;
|
|
if(x > boat.x)
|
|
x := x + 5;
|
|
else
|
|
x := x - 5;
|
|
endif
|
|
if(y > boat.y)
|
|
y := y + 5;
|
|
else
|
|
y := y - 5;
|
|
endif
|
|
z := GetMapInfo(x, y).z;
|
|
if(z >= who.z)
|
|
return;
|
|
endif
|
|
var it := CreateNpcFromTemplate(getcritter(), x, y, z, 0);
|
|
if(it)
|
|
SetObjProperty(it,"killme",1);
|
|
endif
|
|
var ev := {};
|
|
ev.+type := EVID_ENTEREDAREA;
|
|
ev.+source := who;
|
|
SendEvent(it, ev);
|
|
endfunction
|
|
|
|
function checkres()
|
|
foreach who in ListMobilesNearLocationEx(boat.x, boat.y, GetMapInfo(boat.x, boat.y).z, 4, LISTEX_FLAG_GHOST)
|
|
if(who in boat.mobiles)
|
|
if(YesNo(who,"Resurrect?"))
|
|
PlaySoundEffect(who, SFX_SPELL_RESSURECTION);
|
|
PlaySoundEffect(who, SFX_SPELL_RESSURECTION);
|
|
Resurrect(who);
|
|
endif
|
|
endif
|
|
endforeach
|
|
endfunction
|
|
|
|
function getcritter()
|
|
case(RandomInt(9))
|
|
0: return "walrus";
|
|
1: return "walrus";
|
|
2: return "walrus";
|
|
3: return "walrus";
|
|
4: return "alligator";
|
|
5: return "alligator";
|
|
6: return "waterelemental";
|
|
7: return "seaserpent";
|
|
8: return "airelemental";
|
|
endcase
|
|
endfunction
|
|
|
|
function drydock(event)
|
|
if(GetObjProperty(event.source, "#DryDocking"))
|
|
SendSysMessage(event.source, "You are already doing something else.");
|
|
return;
|
|
endif
|
|
SetObjProperty(event.source, "#DryDocking", 1);
|
|
EraseObjProperty(event.source, "#DryDocking");
|
|
var text := lower(event.text);
|
|
if(!text["drydock"])
|
|
EraseObjProperty(event.source, "#DryDocking");
|
|
return;
|
|
endif
|
|
var me := event.source;
|
|
var items := boat.items;
|
|
if(len(items) > 0)
|
|
PrintTextAbovePrivate(boat.tillerman, "You cannot drydock the boat while items are on deck.", me);
|
|
EraseObjProperty(me, "#DryDocking");
|
|
return;
|
|
endif
|
|
items := EnumerateItemsInContainer(boat.hold);
|
|
if(len(items) > 0)
|
|
PrintTextAbovePrivate(boat.tillerman, "You cannot drydock the boat while items are in the hold.", me);
|
|
EraseObjProperty(me, "#DryDocking");
|
|
return;
|
|
endif
|
|
if(CanDockMe(boat, me))
|
|
if(!YesNo(me,"Drydock?"))
|
|
EraseObjProperty(me, "#DryDocking");
|
|
return;
|
|
endif
|
|
|
|
var shiptype;
|
|
case(boat.objtype)
|
|
0x6040: shiptype := 0x6027;
|
|
0x6041: shiptype := 0x6028;
|
|
0x6042: shiptype := 0x6029;
|
|
0x6043: shiptype := 0x602a;
|
|
0x6044: shiptype := 0x602b;
|
|
0x6045: shiptype := 0x602c;
|
|
endcase
|
|
|
|
if(!shiptype)
|
|
SendSysMessage(me, "Your boat seems to be malfunctioning. Please page a GM.");
|
|
return;
|
|
endif
|
|
|
|
var newboat := CreateItemInContainer(me.backpack, shiptype, 1);
|
|
var key := FindKey(me, boat.tillerman);
|
|
if(key)
|
|
DestroyItem(key);
|
|
endif
|
|
if(!newboat)
|
|
SendSysMessage(me,"Could not create boat deed in your backpack!");
|
|
EraseObjProperty(me, "#DryDocking");
|
|
return;
|
|
endif
|
|
if(ReserveItem(newboat))
|
|
newboat.graphic := 0x14f3;
|
|
if(!boat.tillerman.name)
|
|
newboat.name := "a toy boat";
|
|
else
|
|
newboat.name := boat.tillerman.name;
|
|
endif
|
|
|
|
if(!DestroyBoat(boat))
|
|
DestroyItem(newboat);
|
|
endif
|
|
else
|
|
DestroyItem(newboat);
|
|
endif
|
|
endif
|
|
EraseObjProperty(me, "#DryDocking");
|
|
endfunction
|
|
|
|
function DestroyBoat(who)
|
|
var res := DestroyMulti(boat);
|
|
if(!res)
|
|
return 0;
|
|
endif
|
|
return 1;
|
|
endfunction
|
|
|
|
function SmackEveryone()
|
|
foreach mob in(boat.mobiles)
|
|
ApplyDamage(mob,RandomInt(10));
|
|
PerformAction(mob,0x14);
|
|
PlaySoundEffect(mob,0x110);
|
|
endforeach
|
|
endfunction
|
|
|
|
function PlayBoatSounds()
|
|
var who := RandomInt(len(boat.mobiles)+1);
|
|
var mobs :=(boat.mobiles);
|
|
if(RandomInt(2) == 1)
|
|
PlaySoundEffect(mobs[who],0x13);
|
|
else
|
|
PlaySoundEffect(mobs[who],0x14);
|
|
endif
|
|
endfunction
|
|
|
|
function WorldWrap()
|
|
var newx := boat.x;
|
|
var newy := boat.y;
|
|
if(boat.y <= 6)
|
|
newy := 4088;
|
|
elseif(boat.y >= 4089)
|
|
newy := 6;
|
|
endif
|
|
if(boat.x <= 6)
|
|
newx := 5096;
|
|
elseif(boat.x >= 5097)
|
|
newx := 6;
|
|
endif
|
|
var lockid := GetObjProperty(boat.hold, "lockid");
|
|
var owner := GetObjProperty(boat.hold, "owner");
|
|
var shiptype := boat.objtype;
|
|
var shipfacing, created;
|
|
case(tillerman.graphic)
|
|
0x3e4e: shipfacing := CRMULTI_FACING_NORTH;
|
|
0x3e55: shipfacing := CRMULTI_FACING_EAST;
|
|
0x3e4b: shipfacing := CRMULTI_FACING_SOUTH;
|
|
0x3e50: shipfacing := CRMULTI_FACING_WEST;
|
|
default: shipfacing := "Error!";
|
|
endcase
|
|
if(shipfacing="Error!")
|
|
syslog( "[ERROR] [boat.src] Couldn't tell which way the ship was facing for the worldwrap!");
|
|
endif
|
|
created := CreateMultiAtLocation( newx, newy, -5, shiptype, shipfacing);
|
|
if(!created)
|
|
syslog( "[ERROR] [boat.src] New ship couldn't be created for worldwrap!");
|
|
return;
|
|
endif
|
|
var oldshiphold := boat.hold;
|
|
var newshiphold := created.hold;
|
|
foreach item in EnumerateItemsInContainer( oldshiphold )
|
|
if(item.container = oldshiphold)
|
|
MoveItemToContainer(item, newshiphold);
|
|
endif
|
|
endforeach
|
|
foreach item in EnumerateItemsInContainer( oldshiphold )
|
|
MoveItemToContainer(item, newshiphold);
|
|
endforeach
|
|
foreach mob in(boat.mobiles)
|
|
MoveCharacterToLocation(mob,(mob.x-boat.x)+created.x,(mob.y-boat.y)+created.y, -2, MOVECHAR_FORCELOCATION );
|
|
endforeach
|
|
if(boat.has_offline_mobiles)
|
|
foreach mob in(boat.offline_mobiles)
|
|
MoveCharacterToLocation(mob,(mob.x-boat.x)+created.x,(mob.y-boat.y)+created.y, -2, MOVECHAR_FORCELOCATION );
|
|
endforeach
|
|
endif
|
|
foreach mob in(boat.items)
|
|
MoveitemToLocation(mob,(mob.x-boat.x)+created.x,(mob.y-boat.y)+created.y, -2,0 );
|
|
endforeach
|
|
var newtillerman := created.tillerman;
|
|
newtillerman.name := tillerman.name;
|
|
SetObjProperty( created.starboardplank, "lockid", lockid);
|
|
SetObjProperty( created.portplank, "lockid", lockid);
|
|
SetObjProperty( created.ship.starboardplank, "owner", owner );
|
|
SetObjProperty( created.ship.portplank, "owner", owner );
|
|
SetObjProperty( created.ship.starboardplank, "tillermanid", newtillerman.serial );
|
|
SetObjProperty( created.ship.portplank, "tillermanid", newtillerman.serial );
|
|
SetObjProperty( created.hold, "lockid", lockid);
|
|
SetObjProperty( created.hold, "owner", owner);
|
|
SetObjProperty( created.tillerman, "owner", owner);
|
|
SetObjProperty( created.tillerman, "shipserial", created.serial);
|
|
SetObjProperty( created.tillerman, "lockid", lockid);
|
|
SetObjProperty( created.tillerman, "decay", decay);
|
|
if(boat.starboardplank.locked = 1)
|
|
created.starboardplank.locked := 1;
|
|
endif
|
|
if(boat.portplank.locked = 1)
|
|
created.portplank.locked := 1;
|
|
endif
|
|
if(boat.hold.locked = 1)
|
|
created.hold.locked := 1;
|
|
endif
|
|
SetObjProperty( created.hold, "#relativedir", relative_direction);
|
|
SetObjProperty( created.hold, "#speed", ms_delay_between_moves);
|
|
created.tillerman.usescript := ":boat:tillerman";
|
|
if(!DestroyMulti(boat))
|
|
DestroyItem(boat.tillerman);
|
|
syslog( "[ERROR] [boat.src] Old ship at " +(boat.x-1) +","+ boat.y +","+ boat.z + " couldn't be destroyed during worldwrap!");
|
|
endif
|
|
endfunction
|
|
|
|
function CanDockMe(boat, who)
|
|
if(GetObjProperty(boat.hold,"owner") == who.serial)
|
|
return 1;
|
|
else
|
|
var packkey;
|
|
var lokid := GetObjProperty(boat.tillerman, "lockid");
|
|
foreach thing in EnumerateItemsInContainer(who.backpack)
|
|
if(GetObjProperty(thing, "lockid") = lokid)
|
|
packkey := 1;
|
|
break;
|
|
endif
|
|
endforeach
|
|
if(packkey = 1)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
/*NEW MAP COURSE FUNCTIONS*/
|
|
//follows the current course
|
|
function BoatFollowCourse(boat)
|
|
var startx, starty, destx, desty;
|
|
var course, nextwaypoint;
|
|
var newpoint, newfacing, prevfacing;
|
|
|
|
course := GetObjProperty(boat.tillerman,"course");
|
|
nextwaypoint := GetObjProperty(boat.tillerman,"nextwaypoint");
|
|
startx := boat.x;
|
|
starty := boat.y;
|
|
prevfacing := boat.facing;
|
|
|
|
if( (course==error) || (nextwaypoint==error))
|
|
return;
|
|
endif
|
|
|
|
destx := course[nextwaypoint].x;
|
|
desty := course[nextwaypoint].y;
|
|
|
|
newpoint := lineBresenham(startx,starty,destx,desty);
|
|
newfacing := GetNewFacing(startx,starty,newpoint[1],newpoint[2]);
|
|
|
|
if(newfacing == error) //reached waypoint/end
|
|
nextwaypoint := nextwaypoint + 1;
|
|
first_move_toward_waypoint := 1; //so we turn toward next waypoint (includes next course follow if we're done with this one)
|
|
if(nextwaypoint > course.size()) //done
|
|
state := STATE_DRIFTING;
|
|
PrintTextAbove(boat.tillerman,"Arr, we've reached our destination.");
|
|
return;
|
|
else
|
|
SetObjProperty(boat.tillerman,"nextwaypoint",nextwaypoint);
|
|
endif
|
|
|
|
else
|
|
|
|
if(first_move_toward_waypoint == 1)
|
|
if( prevfacing != newfacing )
|
|
TurnBoat(boat,Cint(DetermineTurnCode(boat,newfacing)) );
|
|
endif
|
|
first_move_toward_waypoint := 0;
|
|
endif
|
|
MoveBoat(boat,newfacing);
|
|
|
|
if((startx == boat.x) &&(starty == boat.y)) //we didn't move. must be blocked
|
|
state := STATE_DRIFTING;
|
|
PrintTextAbove(tillerman, "Aaargh! We've stopped!");
|
|
endif
|
|
endif
|
|
|
|
endfunction
|
|
|
|
//convert facing 0-7 to turn code 0-3
|
|
function DetermineTurnCode( boat, desired )
|
|
|
|
var current := CInt(boat.facing / 2);
|
|
desired := CInt(desired / 2);
|
|
|
|
|
|
if ( desired < current )
|
|
desired := desired + 4;
|
|
endif
|
|
return (desired - current);
|
|
endfunction
|
|
|
|
//returns the direction (x1,y1) lies from (x0,y0) in the range 0-7.
|
|
// returns error if the 2 points are equal.
|
|
function GetNewFacing(x0,y0,x1,y1)
|
|
var dx, dy;
|
|
var facing;
|
|
dx := x1 - x0;
|
|
dy := y1 - y0;
|
|
|
|
case(dx)
|
|
NEGONE:
|
|
case(dy)
|
|
NEGONE: facing := 7;
|
|
ZERO: facing := 6;
|
|
POSONE: facing := 5;
|
|
default: facing := error;
|
|
endcase
|
|
ZERO:
|
|
case(dy)
|
|
NEGONE: facing := 0;
|
|
ZERO: facing := error;
|
|
POSONE: facing := 4;
|
|
default: facing := error;
|
|
endcase
|
|
POSONE:
|
|
case(dy)
|
|
NEGONE: facing := 1;
|
|
ZERO: facing := 2;
|
|
POSONE: facing := 3;
|
|
default: facing := error;
|
|
endcase
|
|
default: facing := error;
|
|
endcase
|
|
|
|
return facing;
|
|
endfunction
|
|
|
|
//Bresenham's line drawing algorithm. determines a line between two waypoints.
|
|
function lineBresenham(x0, y0, x1, y1)
|
|
var dy;
|
|
dy := y1 - y0;
|
|
var dx;
|
|
dx := x1 - x0;
|
|
var stepx, stepy;
|
|
|
|
if (dy < 0)
|
|
dy := -dy;
|
|
stepy := -1;
|
|
else
|
|
stepy := 1;
|
|
endif
|
|
|
|
if (dx < 0)
|
|
dx := -dx;
|
|
stepx := -1;
|
|
else
|
|
stepx := 1;
|
|
endif
|
|
|
|
dy := 2*dy;
|
|
dx := 2*dx;
|
|
|
|
if (dx > dy)
|
|
var fraction;
|
|
fraction := 2*dy - dx;
|
|
while (x0 != x1)
|
|
if (fraction >= 0)
|
|
y0 := y0 + stepy;
|
|
fraction := fraction - dx;
|
|
endif
|
|
x0 := x0 + stepx;
|
|
fraction := fraction + dy;
|
|
return {x0, y0};
|
|
endwhile
|
|
else
|
|
var fraction;
|
|
fraction := 2*dx - dy;
|
|
while (y0 != y1)
|
|
if (fraction >= 0)
|
|
x0 := x0 + stepx;
|
|
fraction := fraction - dy;
|
|
endif
|
|
y0 := y0 + stepy;
|
|
fraction := fraction + dx;
|
|
return {x0, y0};
|
|
endwhile
|
|
endif
|
|
endfunction
|
|
/*END NEW MAP COURSE FUNCTIONS*/
|
|
|