/* Sailing Ship v3.03, Angel January 1994. * * This sailing ship is designed to travel between ports of call, * organised into an array read from the open directory within * /room/islands/open. Any player can write a jetty of their own which * they want the ship to visit on its route around the realms. * It is designed to be copied, altered, and inherited as needed. * * The ships are also in an open dir so that players can buy ships * with automatic writes to the directory */ #define PORT_FILE "/room/ships/open/ports.h" #define SHIP_DIR "/room/ships/open/types/" #define DISTANCE "/room/ships/distance" #define START "/room/city/jetty" #define ABANDON_SHIP "/room/island/beach5" #define SHIP_OB_FILE "stern" /* where to find other ship fns */ #define NAME (string)this_player()->query_name() #define SHIP_NAME capitalize(this_object()->query_short()) #define CAPTAIN "Captain" #define WAIT_TIME 60 /* a few minutes */ #define X 0 /* members of an array for coords */ #define Y 1 #define SPEED 5 /* default speed of ship */ #define SIGHT_RANGE 100 /* range of the looking glass */ #define CLOSE_ENUFF 2 #define HP 1000 /* hp for the ship */ #include <mudlib.h> #include <linewrap.h> #include PORT_FILE inherit ROOM; mixed *destinations; /* places to sail to */ status sailing; /* for the init to set_heart_beat() */ status waiting; /* if the ship is waiting to move on */ string ship_name; /* name of the ship for exit array */ string captain; /* captain's name */ string port, port_file, port_long, port_list; int timer, counter, distance, *old_port_coords, *port_coords, wait_time; int speed, hull_points; /*************************************************************************/ /* Fn Specs */ int query_coordinates(); mixed *check_ships(); void set_sail(string str); void msg(string message); /*************************************************************************/ /* Room Stuff */ void reset(status arg) { string txt; if(arg) return; set_short("the sutherland"); set_long( "A tall mast with spinnaker flying from it towers above you on this \n"+ "grand sailing ship. Three other sails are full with the sea winds \n"+ "pushing the ship ever closer to its port of call; your destination.\n"); set_items(({ "spinnaker", "A huge sail full of wind. Upon the spinnaker is a design \n"+ "of a naked woman with the lower body of a great wave", "mast", "The spinnaker flies from the mast", "ship", "You're standing on it", "sail#sails", "The wind fills them, pushing the ship along in the water", "wind#winds", "You can't see the wind!", /* someone is bound to do it! */ "sea#water#wave#waves", "They crash against the ship, making it toss up and "+ "down in the water", "wheel", "The ships wheel is painted a rusty brown, matching the wood \n"+ "on the rest of the ship. Beside it is a compass, as well as "+ "a brass telescope", })); set_weather(2, 4, 6); set_exits(({ "room/city/jetty", "gang plank", })); set_night_desc( "A lantern hangs by the wheel, lighting the upper decks.\n"); set_night_items(({ "lantern", "A simple oil lantern made from brass", })); } void long(status wiz) { string tmp, temp; ::long(wiz); temp = capitalize(ship_name); tmp = "There is a map beside the ships' wheel with the destination "+ capitalize(destinations[counter][0]+" circled in ink. "); if(hull_points > hull_points/2) tmp += "The "+temp+" is in excelent shape.\n"; else if(hull_points > hull_points/3) tmp += "The "+temp+" is looking a little shabby.\n"; else if(hull_points > hull_points/4) tmp += "The "+temp+" is showing some wear and tear.\n"; else if(hull_points > hull_points/5) tmp += "The "+temp+" looks quite damaged.\n"; else tmp += "The "+temp+" is falling appart!\n"; if(hull_points < 0) tmp += "The "+temp+" is sinking!\n"; writelw(tmp); } void init() { if(!sailing) { if(!destinations) { destinations = PORTS; /* from the included file */ destinations += ({ ({ "tempus city", START, ({ 0, 0, }), }), }); /* array is as follows: harbour file ({ x,y coords }) */ } if(!wait_time) wait_time = WAIT_TIME; if(!captain) captain = CAPTAIN; if(!hull_points) hull_points = HP; if(!ship_name) ship_name = "sutherland"; /* data's nebula ship! */ counter = 0; port_file = START; /* where we start off */ port = "skol island"; old_port_coords = ({ 0, 0, }); port_long = port_file -> query_long(); call_out("set_sail", WAIT_TIME, destinations[0][0]); sailing = 1; waiting = 1; distance = 141; /* an arbitary distance */ } ::init(); } /*************************************************************************/ /* Special looks at functions */ status look_at(string str) { string tmp, tmp1, tmp2; int i, j, *ship_xy, *my_xy, *dest_xy; string ship_file; mixed *ships; if(str == "map") { tmp = "The map shows that the ship has many destinations, including "; for(i=0; i<sizeof(destinations); i++) { if((sizeof(destinations)-1) == i) tmp += "and "+capitalize(destinations[i][0])+". "; else tmp += capitalize(destinations[i][0])+", "; } tmp += "From the map "+capitalize(destinations[counter][0])+ " is about "+(distance - timer)+" nautical miles away from here.\n"; writelw(tmp); return 1; } if(str == "compass") { tmp = "From the compass settings you think you're sailing in "; my_xy = (int *)this_object()->query_coordinates(); dest_xy = (int *)this_object()->query_port_coords(); tmp1 = (string)DISTANCE -> calc_direction(my_xy, dest_xy); if(tmp1[0] == 'e') tmp += "an "+tmp1; else tmp += "a "+tmp1; tmp += "erly direction.\n"; writelw(tmp); return 1; } if(str == "telescope") { ships = check_ships(); /* placement of other ships ...except outs */ write("You look through the telescope...\n"); say(this_player()->query_name()+" looks through the telescope.\n", this_player()); if(!sizeof(ships)) write("There are no ships within sight.\n"); else { for(i=0; i<sizeof(ships); i++) { if(ships[i][1] < SIGHT_RANGE) { tmp = "You can see the "; tmp += capitalize(ships[i][0]); if(ships[i][1] < CLOSE_ENUFF) tmp += ". It's only a few yards "; else { tmp += ". It's about "+ships[i][1]+" nautical miles "; tmp += ships[i][2]+" from here.\n"; } j++; writelw(tmp); } } } if(!j) { write("There are no ships within sight.\n"); } if((distance - timer) < SIGHT_RANGE) { write("You can see that "+capitalize(port)+" is only "+ (distance - timer)+" nautical miles away.\n"); } else { write("You can't see your destination yet.\n"); } return 1; } return ::look_at(str); } /*************************************************************************/ /* Set Funs */ int set_ship_hp(int i) { return hull_points = i; } int set_ship_speed(int i) { return speed = i; } int set_wait_time(int i) { return wait_time = i; } mixed *set_destinations(mixed *arr) { return destinations = arr; } string set_ship_name(string str) { return ship_name = str; } string set_captain(string str) { return captain = str; } /*************************************************************************/ /* Major Ship Sailing Fn */ void heart_beat() { mixed *arr; int i; if(!speed && hull_points > 0) speed = SPEED; timer += speed; /* wait for a while before setting off again */ if(waiting) { if(timer > WAIT_TIME) { set_sail(destinations[counter][0]); timer = 0; waiting = 0; return; } } if(timer >= distance) { msg("The ship finally reaches "+capitalize(port)+".\n"+ capitalize(captain)+" says: Right then, we're here mates!\n"+ "The gang plank is pulled out toward the jetty\n"); port_long = port_file->query_long(); port_file -> set_long(port_long+ SHIP_NAME+" has dropped anchor here, "+ "in the harbour.\n"); this_object() -> add_exit(port_file, "gang plank"); port_file -> add_exit(file_name(this_object()), ship_name); port_file -> add_item("gang plank#plank", "It leads onto the "+ship_name); port_file -> add_item(ship_name, SHIP_NAME+", with its gang plank set down close by.\n"+ "The ship looks as if it may set sail at any moment"); tell_room(port_file, SHIP_NAME+" sails into the harbour...\n"); old_port_coords = destinations[counter][2]; /* where we are now */ if(counter >= sizeof(destinations)-1) counter = 0; /* next destination */ else counter ++; waiting = 1; /* wait for a little while before setting off */ timer = 0; return; } if(!random(10)) { if(arr = check_ships()) for(i=0; i<sizeof(arr); i++) { if(arr[i][1] < CLOSE_ENUFF) { msg("You notice the "+capitalize(arr[i][0])+" passing close by to "+ "the "+arr[i][2]+"...\n"); } } } } void set_sail(string str) { msg(capitalize(captain)+" exclaims: Right then maties! Set sail for "+ capitalize(str)+" harbour!\n"); set_heart_beat(1); if(port_file) { /* put the room back the way we found it */ port_file -> remove_exit(ship_name); port_file -> remove_item("gang plank#plank"); port_file -> remove_item(ship_name); port_file -> set_long(port_long); tell_room(port_file, SHIP_NAME+" sails out of the harbour...\n"); } this_object() -> remove_exit("gang plank"); port = destinations[counter][0]; port_file = destinations[counter][1]; port_coords = destinations[counter][2]; /* where we want to go */ /* calc distance from here to there */ distance = (int)DISTANCE->calc_distance(port_coords, old_port_coords); msg("The anchor is pulled up onto the deck.\n"); msg("The gang plank is pulled in, and the ship sets sail.\n"); timer = 0; waiting = 0; return; } mixed *check_ships() { int i, j, *dest_xy, *my_xy; string *ships, tmp, ship_file, k; mixed *result; ships = get_dir(SHIP_DIR); if(!sizeof(ships)) return 0; result = ({}); for(i=0; i<sizeof(ships); i++) { if(!sscanf(ships[i], "%s.c", tmp)) { ship_file = SHIP_DIR+ships[i]+"/"+SHIP_OB_FILE; if((string)ship_file->query_ship_name() != ((string)this_object()->query_ship_name())) { dest_xy = (int *)call_other(ship_file, "query_coordinates"); my_xy = (int *)this_object()->query_coordinates(); if(dest_xy && my_xy) { j = (int)DISTANCE->calc_distance(my_xy, dest_xy); tmp = capitalize((string)ship_file->query_ship_name()); k = (string)DISTANCE->calc_direction(my_xy, dest_xy); result += ({ ({ tmp, j, k, }), }); } } } } return result; } mixed *query_coordinates() { int x1, x2, y1, y2, dx, dy; int gradient; int x, y; if(waiting) return old_port_coords; if(!timer) return old_port_coords; x1 = old_port_coords[X]; x2 = port_coords[X]; y1 = old_port_coords[Y]; y2 = port_coords[Y]; dx = x2 - x1; dy = y2 - y1; x = (dx * timer)/distance; y = (dy * timer)/distance; return ({ (x1 + x), (y1 + y), }); } void msg(string message) { tell_room(this_object(), message); return; } int hit_ship(int dmg) { hull_points -= dmg; if(hull_points < 0) { msg("The ship starts to sink!\n"); msg(capitalize(captain)+" exclaims: Abandon ship! We're sinking!\n"); set_heart_beat(0); this_object()->add_exit(ABANDON_SHIP, "overboard"); } else { if(hull_points/dmg) speed /= (hull_points/dmg); if(speed < 1) speed = 1; msg(SHIP_NAME+" slows in the water due to hull damage.\n"); set_heart_beat(1); } return hull_points; } int *query_port_coords() { return port_coords; } int *query_old_port_coords() { return old_port_coords; } int query_ship_hp() { return hull_points; } string query_ship_name() { return ship_name; } string query_captain() { return captain; } mixed *query_destinations() { return destinations; }