// $Id: vehicle.cc,v 1.4.2.4 2000/05/03 02:25:14 justin Exp $ // $Revision: 1.4.2.4 $ $Author: justin $ $Date: 2000/05/03 02:25:14 $ // //ScryMUD Server Code //Copyright (C) 1998 Ben Greear // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either version 2 //of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred) // greearb@agcs.com // ///************************* Vehicle *****************************/// #include "vehicle.h" #include "const.h" #include <PtrArray.h> #include "room.h" #include "misc.h" #include "misc2.h" #include "commands.h" vehicle::vehicle() { path_cells.head(cll); cll.next(); //move to first one. ticks_till_next_stop = in_room = cur_fuel = max_fuel = 0; ticks_between_stops = 0; } vehicle::vehicle(int num) : room(num) { path_cells.head(cll); cll.next(); //move to first one. ticks_till_next_stop = in_room = cur_fuel = max_fuel = 0; ticks_between_stops = 0; } vehicle::~vehicle() { clear_ptr_list(path_cells); } int vehicle::canEnter(const room* dest_room, int do_msg) const { int retval = FALSE; String buf(100); if (!(hasUnlimitedFuel() || (cur_fuel > 0))) { if (do_msg) { Sprintf(buf, "%S is out of fuel.\n", &(short_desc)); showAllCept(buf); }//if }//if else if (!dest_room->isInUse()) { //if not used if (do_msg) showAllCept("That room doesn't really exist!!\n"); }//if else if (dest_room->isNoVehicle()) { //!vehicle if (do_msg) showAllCept("Vehicles cannot travel there.\n"); }//if else if (dest_room->needsBoat() && !(canFloat() || canFly())) { if (do_msg) showAllCept("This vehicle can't travel on water.\n"); }//if else if ((dest_room->needsClimb()) && (!(canClimb() || canFly()))) { if (do_msg) showAllCept("This vehicle can't climb.\n"); }//if else if ((dest_room->needsDive()) && (!canDive())) { if (do_msg) showAllCept("This vehicle can't dive.\n"); }//if else if ((dest_room->needsFly()) && (!canFly())) { if (do_msg) showAllCept("This vehicle can't fly.\n"); }//if else if (dest_room->isZlocked()) { //is zlocked if (do_msg) showAllCept("That direction has been locked to vehicles.\n"); }//if else retval = TRUE; return retval; }//canEnter void vehicle::setInRoom(int i) { if (i < 0) i = 0; if (i > NUMBER_OF_ROOMS) i = 0; in_room = i; } int vehicle::move() { return move(~0, getExitNum(), getExitDirection()); } void vehicle::stat(critter& pc) { room::stat(pc); show("\n\t\t\tIS A VEHICLE\nVehicle flags:\n", pc); out_field(vehicle_flags, pc, VEHICLE_FLAGS_NAMES); String buf(200); Sprintf(buf, "ticks_till_next_stop: %i, in_room: %i, cur_fuel: %i\n", ticks_till_next_stop, in_room, cur_fuel); show(buf, pc); Sprintf(buf, "Max fuel: %i, ticks_between_stops: %i\n", max_fuel, ticks_between_stops); show(buf, pc); }//stat int vehicle::move(int see_bit, int i_th, const String& exit_direction) { int dest; String buf(200); if (mudlog.ofLevel(DBG)) { mudlog << "In vehicle::move, in_room: " << in_room << " see_bit: " << see_bit << " i_th: " << i_th << " exit dir -:" << exit_direction << ":-" << endl; } ticks_till_next_stop = ticks_between_stops; door* exit_dr_ptr = door::findDoor(room_list[in_room].DOORS, i_th, &exit_direction, see_bit, room_list[in_room].getVisBit()); //log("Got exit_dr_ptr.\n"); if (!exit_dr_ptr) { //mudlog.log(WRN, "WARNING: destination dr_ptr is NULL in move_room.\n"); Sprintf(buf, "Your vehicle cannot go %S.\n", &exit_direction); showAllCept(buf); return FALSE; }//if dest = abs(exit_dr_ptr->destination); if (mudlog.ofLevel(DBG)) { mudlog << "got dest: " << dest << endl; } if (!canEnter(&room_list[dest], TRUE)) { mudlog.log(WRN, "WARNING: vehicle::can_enter failed in vehicle::move\n"); return FALSE; }//if ticks_till_next_stop += exit_dr_ptr->distance; if (mudlog.ofLevel(DBG)) { mudlog << "Passed tests, looking for doors to vehicle, size list: " << room_list[in_room].DOORS.size() << endl; } /* passed all tests, lets move it!! */ /* delete door(s) TO the car */ Cell<door*> dcll(room_list[in_room].DOORS); door* tmp_ptr = NULL; door* dr_ptr = dcll.next(); while (dr_ptr) { if (mudlog.ofLevel(DBG)) { mudlog << "Comparing dest: " << abs(dr_ptr->destination) << " and this room num: " << getRoomNum() << endl; } if (abs(dr_ptr->destination) == getRoomNum()) { //mudlog.log(DBG, "They were equal.\n"); tmp_ptr = dr_ptr; dr_ptr = room_list[in_room].DOORS.lose(dcll); }//if else { //mudlog.log(DBG, "They were not equal."); dr_ptr = dcll.next(); } }//if /* save tmp_ptr, it can be reused in next room */ mudlog.log(DBG, "Found tmp_ptr.\n"); if (!tmp_ptr) { //the train door, the exterior one mudlog.log(ERROR, "ERROR: tmp_ptr is NULL in vehicle::move()\n"); return FALSE; }//if if (!tmp_ptr->dr_data) { mudlog.log(ERROR, "ERROR: dr_data is null.\n"); return FALSE; }//if mudlog.log(DBG, "About to do messages.\n"); dr_ptr = NULL; // lets find the door from the train to the outside. DOORS.head(dcll); //head of vehicle doors while ((dr_ptr = dcll.next())) { if (dr_ptr->dr_data == tmp_ptr->dr_data) { break; } }//while /* show messages to room, the one BEFORE the move */ if (!isStealthy()) { //if not stealth if (isAtDestination() && tmp_ptr->dr_data->isOpen() && tmp_ptr->dr_data->canClose()) { if (dr_ptr) { Sprintf(buf, "The %S closes.\n", name_of_door(*dr_ptr, ~0)); showAllCept(buf); } else { mudlog.log(ERROR, "ERROR: dr_ptr is NULL...\n"); } Sprintf(buf, "The %S closes.\n", name_of_door(*tmp_ptr, ~0)); room_list[in_room].showAllCept(buf); tmp_ptr->dr_data->close(); //make it closed }//if Sprintf(buf, "%S leaves towards the %S.\n", &(short_desc), &exit_direction); room_list[in_room].showAllCept(buf); }//if not stealth /* make vehicle door exit to new room */ mudlog.log(DBG, "About to update vehicle door.\n"); if (!hasUnlimitedFuel()) { cur_fuel -= room_list[in_room].getMovCost(); } DOORS.head(dcll); //list of doors to/from vehicle while ((dr_ptr = dcll.next())) { if (abs(dr_ptr->destination) == abs(in_room)) { //if is_vehicle_exit if (dr_ptr->destination < 0) dr_ptr->destination = -(abs(dest)); else dr_ptr->destination = abs(dest); break; }//if }//while /* vehicle door now points to next room */ in_room = dest; //guaranteed to be positive mudlog.log(ERROR, "Vehicle door updated.\n"); /* add door to destination room */ room_list[in_room].DOORS.prepend(tmp_ptr); advancePathIterator(); /* advance the internal state, let this object know that it's actually been moved. */ mudlog.log(ERROR, "In new room..doing messages.\n"); /* now in new room, do some messages if needed */ if (!isStealthy()) { //if not stealty Sprintf(buf, "%S has arrived.\n", &(short_desc)); room_list[in_room].showAllCept(buf); }//if not stealth dr_ptr = NULL; // lets find the door from the train to the outside. DOORS.head(dcll); //head of vehicle doors while ((dr_ptr = dcll.next())) { if (dr_ptr->dr_data == tmp_ptr->dr_data) { break; } }//while if (isAtDestination()) { //in other words, the one its in NOW if (!isStealthy() && tmp_ptr->dr_data->isClosed()) { if (dr_ptr) { Sprintf(buf, "The %S opens.\n", name_of_door(*dr_ptr, ~0)); showAllCept(buf); } else { mudlog.log(ERROR, "ERROR: dr_ptr is NULL, end of move.\n"); } if (tmp_ptr) { Sprintf(buf, "The %S opens.\n", name_of_door(*tmp_ptr, ~0)); room_list[in_room].showAllCept(buf); } else { mudlog.log(ERROR, "ERROR: tmp_ptr is NULL, end of move.\n"); } }//if tmp_ptr->dr_data->open(); //make it open }//if buf = getPassengerMessage(); if (buf.Strlen() > 0) { showAllCept(buf); }//if if (vehicle_flags.get(7)) { //if can see out critter* cptr; Cell<critter*> ccll(CRITTERS); while ((cptr = ccll.next())) { do_look(1, &NULL_STRING, *cptr, room_list[in_room], TRUE); /* ignore brief */ }//while }//if can see out return TRUE; }//move // If cll is currently 'pointing' to a room that // is a destination, return true int vehicle::isAtDestination() { PathCell* data = cll.item(); return (data && data->isDest()); } int vehicle::isSelfGuided() const { return vehicle_flags.get(0); } int vehicle::isStealthy() const { return vehicle_flags.get(1); } int vehicle::hasUnlimitedFuel() const { return vehicle_flags.get(2); } int vehicle::canFly() const { return vehicle_flags.get(3); } int vehicle::canClimb() const { return (vehicle_flags.get(4) || canFly()); } int vehicle::canFloat() const { return (vehicle_flags.get(5) || canFly()); } int vehicle::canDive() const { return vehicle_flags.get(6); } void vehicle::decrementTicksTillNextStop() { ticks_till_next_stop--; } int vehicle::getTicksTillNextStop() const { return ticks_till_next_stop; } void vehicle::advancePathIterator() { //iterate past end of the list. if (!cll.next()) cll.next(); } String vehicle::getPassengerMessage() { PathCell* ptr = cll.item(); if (ptr) return ptr->getDesc(); else return UNKNOWN_DESC; } String vehicle::getExitDirection() { PathCell* ptr = cll.item(); if (ptr) return ptr->getDir(); else return UNKNOWN; } // get the i_th exit value int vehicle::getExitNum() { PathCell* ptr = cll.item(); if (ptr) return ptr->getDirNum(); else return 1; } void vehicle::Clear() { room::Clear(); vehicle_flags.Clear(); clear_ptr_list(path_cells); path_cells.head(cll); ticks_till_next_stop = in_room = cur_fuel = max_fuel = 0; ticks_between_stops = 0; } void vehicle::showPaths(critter& pc) { Cell<PathCell*> cell(path_cells); PathCell* ptr; int i = 0; while ((ptr = cell.next())) { ptr->stat(getRoomNum(), i, pc); pc.show("\n"); i++; } }//showPaths void vehicle::insertPathCell(int index, PathCell* pcell) { path_cells.insertAt(index, pcell); } PathCell* vehicle::hasPathCell(int path_cell_num) { return path_cells.elementAt(path_cell_num); } void vehicle::remPathCell(int path_cell_num) {//deletes it from memory PathCell* ptr = path_cells.removeAt(path_cell_num); if (ptr) delete ptr; //now, reset the cell pointing to the next direction... path_cells.head(cll); cll.next(); } void vehicle::setPathPointer(int index) { if ((path_cells.size() > index) || (index < 0)) index = 0; PathCell* ptr; path_cells.head(cll); int i = 0; while ((ptr = cll.next())) { if (i == index) { return; }//if i++; }//while }//setPathPointer // Must use the number as it's stored in the text files for veh_num #ifdef USEMYSQL void vehicle::dbRead(int veh_num, short read_all) { MYSQL_RES* result; MYSQL_ROW row; String query="select * from Vehicles where ROOM_NUM="; query+=veh_num; Clear(); room::dbRead(veh_num, read_all); cur_stats[2] = cur_stats[2] & ~(0x01000000); if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In [function]:\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } return; } row=mysql_fetch_row(result); in_room = atoi(row[VEHTBL_IN_ROOM]); cur_fuel = atoi(row[VEHTBL_CUR_FUEL]); max_fuel = atoi(row[VEHTBL_MAX_FUEL]); ticks_between_stops = atoi(row[VEHTBL_TICKS_BETWEEN_STOPS]); ticks_till_next_stop = ticks_between_stops; vehicle_flags.set(VEHFLAG_SELF_GUIDED, atoi(row[VEHTBL_SELF_GUIDED])); vehicle_flags.set(VEHFLAG_STEALTHY, atoi(row[VEHTBL_STEALTHY])); vehicle_flags.set(VEHFLAG_UNLIMITED_FUEL, atoi(row[VEHTBL_UNLIMITED_FUEL])); vehicle_flags.set(VEHFLAG_FLIES, atoi(row[VEHTBL_FLIES])); vehicle_flags.set(VEHFLAG_CLIMBS, atoi(row[VEHTBL_CLIMBS])); vehicle_flags.set(VEHFLAG_FLOATS, atoi(row[VEHTBL_FLOATS])); vehicle_flags.set(VEHFLAG_DIVES, atoi(row[VEHTBL_DIVES])); vehicle_flags.set(VEHFLAG_CAN_SEE_OUT, atoi(row[VEHTBL_CAN_SEE_OUT])); mysql_free_result(result); } else { if (mudlog.ofLevel(WRN)) { mudlog << "In [function]:\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } return; } } #endif void vehicle::fileRead(ifstream& da_file, short read_all) { Clear(); room::fileRead(da_file, read_all); char tmp[81]; //now, read in vehicle specific stuff... vehicle_flags.Read(da_file); da_file.getline(tmp, 80); int sentinel; PathCell* ptr; da_file >> sentinel; da_file.getline(tmp, 80); while ((sentinel != -1) && da_file) { ptr = new PathCell(); ptr->Read(da_file); Put(ptr, path_cells); da_file >> sentinel; da_file.getline(tmp, 80); } path_cells.head(cll); cll.next(); //da_file.getline(tmp, 80); da_file >> ticks_till_next_stop >> in_room >> cur_fuel >> max_fuel; da_file >> ticks_between_stops; da_file.getline(tmp, 80); }//Read void vehicle::Write(ofstream& da_file) { room::Write(da_file); vehicle_flags.Write(da_file); da_file << endl; Cell<PathCell*> pcell(path_cells); PathCell* ptr; while ((ptr = pcell.next())) { da_file << "1 Beginning of PathCell\n"; ptr->Write(da_file); } da_file << "-1 End of PathCells..\n"; da_file << ticks_till_next_stop << " " << in_room << " " << cur_fuel << " " << max_fuel << " " << ticks_between_stops << " End of Vehicle" << endl; }//write void vehicle::normalize() { room::normalize(); path_cells.head(cll); }//normalize_room