src/hcode/glue.c

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id: glue.c,v 1.4 2005/08/08 09:43:09 murrayma Exp $
00004  *
00005  * Original author: unknown
00006  *
00007  * Copyright (c) 1996-2002 Markus Stenberg
00008  * Copyright (c) 1998-2002 Thomas Wouters 
00009  * Copyright (c) 2000-2002 Cord Awtry 
00010  *
00011  * Last modified: Thu Jul  9 02:40:16 1998 fingon
00012  *
00013  * This includes the basic code to allow objects to have hardcoded
00014  * commands / properties.
00015  *
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <stdio.h>
00021 #include <sys/file.h>
00022 #include <string.h>
00023 #include <math.h>
00024 
00025 #define FAST_WHICHSPECIAL
00026 
00027 #include "create.h"
00028 
00029 #define _GLUE_C
00030 
00031 /*** #include all the prototype here! ****/
00032 #include "mech.h"
00033 #include "mech.events.h"
00034 #include "debug.h"
00035 #include "mechrep.h"
00036 #include "mech.tech.h"
00037 #include "autopilot.h"
00038 #include "turret.h"
00039 #include "p.ds.turret.h"
00040 #include "coolmenu.h"
00041 #include "p.bsuit.h"
00042 #include "glue.h"
00043 #include "mux_tree.h"
00044 #include "powers.h"
00045 #include "ansi.h"
00046 #include "coolmenu.h"
00047 #include "mycool.h"
00048 #include "p.mux_tree.h"
00049 #include "p.mechfile.h"
00050 #include "p.mech.stat.h"
00051 #include "p.mech.partnames.h"
00052 #include "debug.h"
00053 
00054 /* Prototypes */
00055 
00056 /*************CALLABLE PROTOS*****************/
00057 
00058 /* Main entry point */
00059 int HandledCommand(dbref player, dbref loc, char *command);
00060 
00061 /* called when user creates/removes hardcode flag */
00062 void CreateNewSpecialObject(dbref player, dbref key);
00063 void DisposeSpecialObject(dbref player, dbref key);
00064 void list_hashstat(dbref player, const char *tab_name, HASHTAB * htab);
00065 void raw_notify(dbref player, const char *msg);
00066 void AddEntry(Tree * tree, muxkey_t key, dtype_t type, dsize_t size,
00067                           void *data);
00068 void DeleteEntry(Tree * tree, muxkey_t key);
00069 int SaveTree(FILE * f, Tree tree);
00070 void UpdateTree(FILE * f, Tree * tree, int (*sizefunc) (int));
00071 void GoThruTree(Tree tree, int (*func) (Node *));
00072 
00073 /*************PERSONAL PROTOS*****************/
00074 void *NewSpecialObject(int id, int type);
00075 void *FindObjectsData(dbref key);
00076 static Node *FindObjectsNode(dbref key);
00077 static void DoSpecialObjectHelp(dbref player, char *type, int id, int loc,
00078                                                                 int powerneeded, int objid, char *arg);
00079 void initialize_colorize();
00080 
00081 #ifndef FAST_WHICHSPECIAL
00082 
00083 #define WhichSpecialS WhichSpecial
00084 #define WhichType(node) WhichSpecial(NodeKey(node))
00085 int WhichSpecial(dbref key);
00086 
00087 #else
00088 
00089 #define WhichType(node) NodeType(node)
00090 int WhichSpecial(dbref key);
00091 static int WhichSpecialS(dbref key);
00092 
00093 #endif
00094 
00095 /*********************************************/
00096 
00097 HASHTAB SpecialCommandHash[NUM_SPECIAL_OBJECTS];
00098 Tree xcode_tree = NULL;
00099 extern int map_sizefun();
00100 
00101 static int Can_Use_Command(MECH * mech, int cmdflag)
00102 {
00103 #define TYPE2FLAG(a) \
00104     ((a)==CLASS_MECH?GFLAG_MECH:(a)==CLASS_VEH_GROUND?GFLAG_GROUNDVEH:\
00105      (a)==CLASS_AERO?GFLAG_AERO:DropShip(a)?GFLAG_DS:(a)==CLASS_VTOL?GFLAG_VTOL:\
00106      (a)==CLASS_VEH_NAVAL?GFLAG_NAVAL:\
00107      (a)==CLASS_BSUIT?GFLAG_BSUIT:\
00108      (a)==CLASS_MW?GFLAG_MW:0)
00109         int i;
00110 
00111         if(!cmdflag)
00112                 return 1;
00113         if(!mech || !(i = TYPE2FLAG(MechType(mech))))
00114                 return 0;
00115         if(cmdflag > 0) {
00116                 if(cmdflag & i)
00117                         return 1;
00118         } else if(!((0 - cmdflag) & i))
00119                 return 1;
00120         return 0;
00121 }
00122 
00123 int HandledCommand_sub(dbref player, dbref location, char *command)
00124 {
00125         struct SpecialObjectStruct *typeOfObject;
00126         Node *n = NULL;
00127         int type;
00128         CommandsStruct *cmd;
00129         HASHTAB *damnedhash;
00130         char *tmpc, *tmpchar;
00131         int ishelp;
00132 
00133         type = WhichSpecial(location);
00134         if(type < 0 || (SpecialObjects[type].datasize > 0 &&
00135                                         !(n = FindNode(xcode_tree, location)))) {
00136                 if(type >= 0 || !Hardcode(location) || Zombie(location))
00137                         return 0;
00138                 if((type = WhichSpecialS(location)) >= 0) {
00139                         if(SpecialObjects[type].datasize > 0)
00140                                 return 0;
00141                 } else
00142                         return 0;
00143         }
00144 #ifdef FAST_WHICHSPECIAL
00145         if(type > NUM_SPECIAL_OBJECTS)
00146                 return 0;
00147 #endif
00148         typeOfObject = &SpecialObjects[type];
00149         damnedhash = &SpecialCommandHash[type];
00150         tmpc = strstr(command, " ");
00151         if(tmpc)
00152                 *tmpc = 0;
00153         ishelp = !strcmp(command, "HELP");
00154         for(tmpchar = command; *tmpchar; tmpchar++)
00155                 *tmpchar = ToLower(*tmpchar);
00156         cmd = (CommandsStruct *) hashfind(command, &SpecialCommandHash[type]);
00157         if(tmpc)
00158                 *tmpc = ' ';
00159         if(cmd && (type != GTYPE_MECH || (type == GTYPE_MECH &&
00160                                                                           Can_Use_Command(((MECH *)
00161                                                                                                            (NodeData(n))),
00162                                                                                                           cmd->flag)))) {
00163 #define SKIPSTUFF(a) while (*a && *a != ' ') a++;while (*a == ' ') a++
00164                 if(cmd->helpmsg[0] != '@' ||
00165                    Have_MechPower(Owner(player), typeOfObject->power_needed)) {
00166                         SKIPSTUFF(command);
00167                         cmd->func(player, !n ? NULL : NodeData(n), command);
00168                 } else
00169                         notify(player, "Sorry, that command is restricted!");
00170                 return 1;
00171         } else if(ishelp) {
00172                 SKIPSTUFF(command);
00173                 DoSpecialObjectHelp(player, typeOfObject->type, type, location,
00174                                                         typeOfObject->power_needed, location, command);
00175                 return 1;
00176         }
00177         return 0;
00178 }
00179 
00180 #define OkayHcode(a) (a >= 0 && Hardcode(a) && !Zombie(a))
00181 
00182 /* Main entry point */
00183 int HandledCommand(dbref player, dbref loc, char *command)
00184 {
00185         dbref curr, temp;
00186 
00187         if(Slave(player))
00188                 return 0;
00189         if(strlen(command) > (LBUF_SIZE - MBUF_SIZE))
00190                 return 0;
00191         if(OkayHcode(player) && HandledCommand_sub(player, player, command))
00192                 return 1;
00193         if(OkayHcode(loc) && HandledCommand_sub(player, loc, command))
00194                 return 1;
00195         SAFE_DOLIST(curr, temp, Contents(player)) {
00196                 if(OkayHcode(curr))
00197                         if(HandledCommand_sub(player, curr, command))
00198                                 return 1;
00199 #if 0                                                   /* Recursion is evil ; let's not do that, this time */
00200                 if(Has_contents(curr))
00201                         if(HandledCommand_contents(player, curr, command))
00202                                 return 1;
00203 #endif
00204         }
00205         return 0;
00206 }
00207 
00208 void InitSpecialHash(int which);
00209 void initialize_partname_tables();
00210 
00211 static MECH *global_kludge_mech;
00212 int global_specials = NUM_SPECIAL_OBJECTS;
00213 
00214 static int remove_from_all_maps_func(Node * tmp)
00215 {
00216         if(WhichType(tmp) == GTYPE_MAP) {
00217                 MAP *map;
00218                 int i;
00219 
00220                 if(!(map = getMap(NodeKey(tmp))))
00221                         return 1;
00222                 for(i = 0; i < map->first_free; i++)
00223                         if(map->mechsOnMap[i] == global_kludge_mech->mynum)
00224                                 map->mechsOnMap[i] = -1;
00225         }
00226         return 1;
00227 }
00228 
00229 void mech_remove_from_all_maps(MECH * mech)
00230 {
00231         global_kludge_mech = mech;
00232         GoThruTree(xcode_tree, remove_from_all_maps_func);
00233 }
00234 
00235 static dbref except_map = -1;
00236 
00237 static int remove_from_all_maps_except_func(Node * tmp)
00238 {
00239         if(WhichType(tmp) == GTYPE_MAP) {
00240                 int i;
00241                 MAP *map;
00242 
00243                 if(NodeKey(tmp) == except_map)
00244                         return 1;
00245                 if(!(map = getMap(NodeKey(tmp))))
00246                         return 1;
00247                 for(i = 0; i < map->first_free; i++)
00248                         if(map->mechsOnMap[i] == global_kludge_mech->mynum)
00249                                 map->mechsOnMap[i] = -1;
00250         }
00251         return 1;
00252 }
00253 void mech_remove_from_all_maps_except(MECH * mech, int num)
00254 {
00255         global_kludge_mech = mech;
00256         except_map = num;
00257         GoThruTree(xcode_tree, remove_from_all_maps_except_func);
00258         except_map = -1;
00259 }
00260 
00261 static int load_update2(Node * tmp)
00262 {
00263         int i = WhichType(tmp);;
00264 
00265         if(i == GTYPE_MECH)
00266                 mech_map_consistency_check(NodeData(tmp));
00267         return 1;
00268 }
00269 
00270 static int load_update4(Node * tmp)
00271 {
00272         MECH *mech;
00273         MAP *map;
00274 
00275         if(WhichType(tmp) == GTYPE_MECH) {
00276                 mech = NodeData(tmp);
00277                 if(!(map = getMap(mech->mapindex))) {
00278                         /* Ugly kludge */
00279                         if((map = getMap(Location(mech->mynum))))
00280                                 mech_Rsetmapindex(GOD, mech, tprintf("%d",
00281                                                                                                          Location(mech->mynum)));
00282                         if(!(map = getMap(mech->mapindex)))
00283                                 return 1;
00284                 }
00285                 if(!Started(mech))
00286                         return 1;
00287                 StartSeeing(mech);
00288                 UpdateRecycling(mech);
00289                 MaybeMove(mech);
00290 
00291         }
00292         return 1;
00293 }
00294 
00295 static int load_update3(Node * tmp)
00296 {
00297         int i = WhichType(tmp);
00298 
00299         if(i == GTYPE_MAP) {
00300                 eliminate_empties((MAP *) NodeData(tmp));
00301                 recalculate_minefields((MAP *) NodeData(tmp));
00302         }
00303         return 1;
00304 }
00305 
00306 static FILE *global_file_kludge;
00307 
00308 static int load_update1(Node * tmp)
00309 {
00310         MAP *map;
00311         int doh;
00312         char mapbuffer[MBUF_SIZE];
00313         MECH *mech;
00314         int i;
00315         int ctemp;
00316 
00317         switch ((i = WhichType(tmp))) {
00318         case GTYPE_MAP:
00319                 map = (MAP *) NodeData(tmp);
00320                 bzero(map->mapobj, sizeof(map->mapobj));
00321                 map->map = NULL;
00322                 strcpy(mapbuffer, map->mapname);
00323                 doh = (map->flags & MAPFLAG_MAPO);
00324                 if(strcmp(map->mapname, "Default Map"))
00325                         map_loadmap(1, map, mapbuffer);
00326                 if(!strcmp(map->mapname, "Default Map") || !map->map)
00327                         initialize_map_empty(map, NodeKey(tmp));
00328                 if(!feof(global_file_kludge)) {
00329                         load_mapdynamic(global_file_kludge, map);
00330                         if(!feof(global_file_kludge))
00331                                 if(doh)
00332                                         load_mapobjs(global_file_kludge, map);
00333                 }
00334                 if(feof(global_file_kludge)) {
00335                         map->first_free = 0;
00336                         map->mechflags = NULL;
00337                         map->mechsOnMap = NULL;
00338                         map->LOSinfo = NULL;
00339                 }
00340                 debug_fixmap(GOD, map, NULL);
00341                 break;
00342         case GTYPE_MECH:
00343                 mech = (MECH *) NodeData(tmp);
00344                 if(!(FlyingT(mech) && !Landed(mech))) {
00345                         MechDesiredSpeed(mech) = 0;
00346                         MechSpeed(mech) = 0;
00347                         MechVerticalSpeed(mech) = 0;
00348                 }
00349                 ctemp = MechCocoon(mech);
00350                 if(MechCocoon(mech)) {
00351                         MechCocoon(mech) = 0;
00352                         initiate_ood((dbref) GOD, mech, tprintf("%d %d %d", MechX(mech), MechY(mech), MechZ(mech)));
00353                         MechCocoon(mech) = ctemp;
00354                 }
00355 
00356                 if(!FlyingT(mech) && Started(mech) && Jumping(mech))
00357                         mech_Rsetxy(GOD, (void *) mech, tprintf("%d %d", MechX(mech),MechY(mech)));
00358         
00359                 MechStatus(mech) &= ~(BLINDED | UNCONSCIOUS | JUMPING | TOWED);
00360                 MechSpecials2(mech) &=
00361                         ~(ECM_ENABLED | ECM_DISTURBANCE | ECM_PROTECTED |
00362                           ECCM_ENABLED | ANGEL_ECM_ENABLED | ANGEL_ECCM_ENABLED |
00363                           ANGEL_ECM_PROTECTED | ANGEL_ECM_DISTURBED);
00364                 MechCritStatus(mech) &= ~(JELLIED | LOAD_OK | OWEIGHT_OK | SPEED_OK);
00365                 MechWalkXPFactor(mech) = 999;
00366                 MechCarrying(mech) = -1;
00367                 MechBoomStart(mech) = 0;
00368                 MechC3iNetworkSize(mech) = -1;
00369                 MechHeatLast(mech) = 0;
00370                 MechCommLast(mech) = 0;
00371                 if(!(MechXPMod(mech)))
00372                         MechXPMod(mech) = 1;            
00373                 for(i = 0; i < FREQS; i++)
00374                         if(mech->freq[i] < 0)
00375                                 mech->freq[i] = 0;
00376                 break;
00377         }
00378         return 1;
00379 }
00380 
00381 /*
00382  * Read in autopilot data
00383  */
00384 static int load_autopilot_data(Node * tmp)
00385 {
00386 
00387         AUTO *autopilot;
00388         int i;
00389 
00390         if(WhichType(tmp) == GTYPE_AUTO) {
00391 
00392                 autopilot = (AUTO *) NodeData(tmp);
00393 
00394                 /* Save the AI Command List */
00395                 /* auto_load_commands(global_file_kludge, autopilot); */
00396         autopilot->commands = dllist_create_list();
00397 
00398                 /* Reset the Astar Path */
00399                 autopilot->astar_path = NULL;
00400 
00401                 /* Reset the weaplist */
00402                 autopilot->weaplist = NULL;
00403 
00404                 /* Reset the profile */
00405                 for(i = 0; i < AUTO_PROFILE_MAX_SIZE; i++) {
00406                         autopilot->profile[i] = NULL;
00407                 }
00408 
00409                 /* Check to see if the AI is in a mech */
00410             /* Need to make this better, check if its got a target whatnot */
00411 
00412 
00413                 if(!autopilot->mymechnum ||
00414                    !(autopilot->mymech = getMech(autopilot->mymechnum))) {
00415                         DoStopGun(autopilot);
00416                 } else {
00417                         if(Gunning(autopilot))
00418                                 DoStartGun(autopilot);
00419                 }
00420 
00421 
00422         }
00423 
00424         return 1;
00425 
00426 }
00427 
00428 static int get_specialobjectsize(int type)
00429 {
00430         if(type < 0 || type >= NUM_SPECIAL_OBJECTS)
00431                 return -1;
00432         return SpecialObjects[type].datasize;
00433 }
00434 
00435 #ifdef BT_ADVANCED_ECON
00436 static void load_econdb()
00437 {
00438         FILE *f;
00439         /* Econ DB */
00440         extern unsigned long long int specialcost[SPECIALCOST_SIZE];
00441         extern unsigned long long int ammocost[AMMOCOST_SIZE];
00442         extern unsigned long long int weapcost[WEAPCOST_SIZE];
00443         extern unsigned long long int cargocost[CARGOCOST_SIZE];
00444         extern unsigned long long int bombcost[BOMBCOST_SIZE];
00445         int count;
00446 
00447         fprintf(stderr, "LOADING: %s\n", mudconf.econ_db);
00448         f = fopen(mudconf.econ_db, "r");
00449         if(!f) {
00450                 fprintf(stderr, "ERROR: %s not found.\n", mudconf.econ_db);
00451                 return;
00452         }
00453         count =
00454                 fread(&specialcost, sizeof(unsigned long long int), SPECIALCOST_SIZE,
00455                           f);
00456         if(count < SPECIALCOST_SIZE) {
00457                 fprintf(stderr, "ERROR: %s specialcost read : %d expected %d\n",
00458                                 mudconf.econ_db, count, SPECIALCOST_SIZE);
00459                 fclose(f);
00460                 return;
00461         }
00462         count =
00463                 fread(&ammocost, sizeof(unsigned long long int), AMMOCOST_SIZE, f);
00464         if(count < AMMOCOST_SIZE) {
00465                 fprintf(stderr, "ERROR: %s ammocost read : %d expected %d\n",
00466                                 mudconf.econ_db, count, AMMOCOST_SIZE);
00467                 fclose(f);
00468                 return;
00469         }
00470         count =
00471                 fread(&weapcost, sizeof(unsigned long long int), WEAPCOST_SIZE, f);
00472         if(count < WEAPCOST_SIZE) {
00473                 fprintf(stderr, "ERROR: %s weapcost read : %d expected %d\n",
00474                                 mudconf.econ_db, count, WEAPCOST_SIZE);
00475                 fclose(f);
00476                 return;
00477         }
00478         count =
00479                 fread(&cargocost, sizeof(unsigned long long int), CARGOCOST_SIZE, f);
00480         if(count < CARGOCOST_SIZE) {
00481                 fprintf(stderr, "ERROR: %s cargocost read : %d expected %d\n",
00482                                 mudconf.econ_db, count, CARGOCOST_SIZE);
00483                 fclose(f);
00484                 return;
00485         }
00486         count =
00487                 fread(&bombcost, sizeof(unsigned long long int), BOMBCOST_SIZE, f);
00488         if(count < BOMBCOST_SIZE) {
00489                 fprintf(stderr, "ERROR: %s bombcost read : %d expected %d\n",
00490                                 mudconf.econ_db, count, BOMBCOST_SIZE);
00491                 fclose(f);
00492                 return;
00493         }
00494         fclose(f);
00495         fprintf(stderr, "LOADING: %s (done)\n", mudconf.econ_db);
00496 }
00497 #endif
00498 
00499 void heartbeat_init();
00500 
00501 static void load_xcode()
00502 {
00503         FILE *f;
00504         byte xcode_version;
00505         int filemode;
00506 
00507         initialize_colorize();
00508         fprintf(stderr, "LOADING: %s\n", mudconf.hcode_db);
00509         f = my_open_file(mudconf.hcode_db, "r", &filemode);
00510         if(!f) {
00511                 fprintf(stderr, "ERROR: %s not found.\n", mudconf.hcode_db);
00512                 return;
00513         }
00514         fread(&xcode_version, 1, 1, f);
00515         if(xcode_version != XCODE_VERSION) {
00516                 fprintf(stderr,
00517                                 "LOADING: %s (skipped xcodetree - version difference: %d vs %d)\n",
00518                                 mudconf.hcode_db, (int) xcode_version, (int) XCODE_VERSION);
00519                 return;
00520         }
00521         UpdateTree(f, &xcode_tree, get_specialobjectsize);
00522         global_file_kludge = f;
00523         GoThruTree(xcode_tree, load_update1);
00524         GoThruTree(xcode_tree, load_update2);
00525         GoThruTree(xcode_tree, load_update3);
00526         GoThruTree(xcode_tree, load_update4);
00527 
00528         /* Read in autopilot data */
00529         GoThruTree(xcode_tree, load_autopilot_data);
00530 
00531         if(!feof(f))
00532                 loadrepairs(f);
00533 
00534         my_close_file(f, &filemode);
00535         fprintf(stderr, "LOADING: %s (done)\n", mudconf.hcode_db);
00536 #ifdef BT_ADVANCED_ECON
00537         load_econdb();
00538 #endif
00539     heartbeat_init();
00540 }
00541 
00542 static int zappable_node;
00543 
00544 static int zap_check(Node * n)
00545 {
00546         if(zappable_node >= 0)
00547                 return 0;
00548         if(!Hardcode(NodeKey(n))) {
00549                 zappable_node = NodeKey(n);
00550                 return 0;
00551         }
00552         return 1;
00553 }
00554 
00555 void zap_unneccessary_hcode()
00556 {
00557         while (1) {
00558                 zappable_node = -1;
00559                 GoThruTree(xcode_tree, zap_check);
00560                 if(zappable_node >= 0)
00561                         DeleteEntry(&xcode_tree, zappable_node);
00562                 else
00563                         break;
00564         }
00565 }
00566 
00567 void LoadSpecialObjects(void)
00568 {
00569         dbref i;
00570         int id, brand;
00571         int type;
00572         void *tmpdat;
00573 
00574         muxevent_initialize();
00575         muxevent_count_initialize();
00576         init_stat();
00577         initialize_partname_tables();
00578         for(i = 0; MissileHitTable[i].key != -1; i++) {
00579                 if(find_matching_vlong_part(MissileHitTable[i].name, NULL, &id,
00580                                                                         &brand))
00581                         MissileHitTable[i].key = Weapon2I(id);
00582                 else
00583                         MissileHitTable[i].key = -2;
00584         }
00585         /* Loop through the entire database, and if it has the special */
00586         /* object flag, add it to our linked list. */
00587         for(i = 0; i < mudstate.db_top; i++)
00588                 if(Hardcode(i) && !Going(i) && !Halted(i)) {
00589                         type = WhichSpecialS(i);
00590                         if(type >= 0) {
00591                                 if(SpecialObjects[type].datasize > 0)
00592                                         tmpdat = NewSpecialObject(i, type);
00593                                 else
00594                                         tmpdat = NULL;
00595                         } else
00596                                 c_Hardcode(i);  /* Reset the flag */
00597                 }
00598         for(i = 0; i < NUM_SPECIAL_OBJECTS; i++) {
00599                 InitSpecialHash(i);
00600                 if(!SpecialObjects[i].updatefunc)
00601                         SpecialObjects[i].updateTime = 0;
00602         }
00603         init_btechstats();
00604         load_xcode();
00605         zap_unneccessary_hcode();
00606 }
00607 
00608 static FILE *global_file_kludge;
00609 
00610 static int save_maps_func(Node * tmp)
00611 {
00612         MAP *map;
00613 
00614         if(WhichType(tmp) == GTYPE_MAP) {
00615                 /* Write mapobjs, if neccessary */
00616                 map = (MAP *) NodeData(tmp);
00617                 save_mapdynamic(global_file_kludge, map);
00618                 if(map->flags & MAPFLAG_MAPO)
00619                         save_mapobjs(global_file_kludge, map);
00620         }
00621         return 1;
00622 }
00623 
00624 /* 
00625  * Save any extra info for the autopilots 
00626  *
00627  * Like their command lists
00628  * or the Astar path if there is one
00629  *
00630  */
00631 static int save_autopilot_data(Node * tmp)
00632 {
00633 
00634         AUTO *a;
00635 
00636         if(WhichType(tmp) == GTYPE_AUTO) {
00637 
00638                 a = (AUTO *) NodeData(tmp);
00639 
00640                 /* Save the AI Command List */
00641                 auto_save_commands(global_file_kludge, a);
00642 
00643                 /* Save the AI Astar Path */
00644 
00645         }
00646 
00647         return 1;
00648 
00649 }
00650 
00651 void ChangeSpecialObjects(int i)
00652 {
00653         /* XXX Unneccessary for now ; 'latest' db
00654            (db.new) is equivalent to 'db' because we don't
00655            _have_ new-db concept ; this is to-be-done project, however */
00656 }
00657 
00658 #ifdef BT_ADVANCED_ECON
00659 static void save_econdb(char *target, int i)
00660 {
00661         FILE *f;
00662         extern unsigned long long int specialcost[SPECIALCOST_SIZE];
00663         extern unsigned long long int ammocost[AMMOCOST_SIZE];
00664         extern unsigned long long int weapcost[WEAPCOST_SIZE];
00665         extern unsigned long long int cargocost[CARGOCOST_SIZE];
00666         extern unsigned long long int bombcost[BOMBCOST_SIZE];
00667         int count;
00668 
00669         switch (i) {
00670         case DUMP_KILLED:
00671                 sprintf(target, "%s.KILLED", mudconf.econ_db);
00672                 break;
00673         case DUMP_CRASHED:
00674                 sprintf(target, "%s.CRASHED", mudconf.econ_db);
00675                 break;
00676         default:                                        /* RESTART / normal */
00677                 sprintf(target, "%s.tmp", mudconf.econ_db);
00678                 break;
00679         }
00680         f = fopen(target, "w");
00681         if(!f) {
00682                 log_perror("SAVE", "FAIL", "Opening econ-save file", target);
00683                 SendDB("ERROR occured during opening of new econ-savefile.");
00684                 return;
00685         }
00686         count =
00687                 fwrite(&specialcost, sizeof(unsigned long long int), SPECIALCOST_SIZE,
00688                            f);
00689         if(count < SPECIALCOST_SIZE) {
00690                 log_perror("SAVE", "FAIL",
00691                                    tprintf("ERROR: %s specialcost wrote : %d expected %d",
00692                                                    target, count, SPECIALCOST_SIZE), target);
00693                 SendDB("ERROR occured during saving of econ-save file");
00694                 fclose(f);
00695                 return;
00696         }
00697         count =
00698                 fwrite(&ammocost, sizeof(unsigned long long int), AMMOCOST_SIZE, f);
00699         if(count < AMMOCOST_SIZE) {
00700                 log_perror("SAVE", "FAIL",
00701                                    tprintf("ERROR: %s ammocost wrote : %d expected %d",
00702                                                    target, count, AMMOCOST_SIZE), target);
00703                 SendDB("ERROR occured during saving of econ-save file");
00704                 fclose(f);
00705                 return;
00706         }
00707         count =
00708                 fwrite(&weapcost, sizeof(unsigned long long int), WEAPCOST_SIZE, f);
00709         if(count < WEAPCOST_SIZE) {
00710                 log_perror("SAVE", "FAIL",
00711                                    tprintf("ERROR: %s weapcost wrote : %d expected %d",
00712                                                    target, count, WEAPCOST_SIZE), target);
00713                 SendDB("ERROR occured during saving of econ-save file");
00714                 fclose(f);
00715                 return;
00716         }
00717         count =
00718                 fwrite(&cargocost, sizeof(unsigned long long int), CARGOCOST_SIZE, f);
00719         if(count < CARGOCOST_SIZE) {
00720                 log_perror("SAVE", "FAIL",
00721                                    tprintf("ERROR: %s cargocost wrote : %d expected %d",
00722                                                    target, count, CARGOCOST_SIZE), target);
00723                 SendDB("ERROR occured during saving of econ-save file");
00724                 fclose(f);
00725                 return;
00726         }
00727         count =
00728                 fwrite(&bombcost, sizeof(unsigned long long int), BOMBCOST_SIZE, f);
00729         if(count < BOMBCOST_SIZE) {
00730                 log_perror("SAVE", "FAIL",
00731                                    tprintf("ERROR: %s bombcost wrote : %d expected %d",
00732                                                    target, count, BOMBCOST_SIZE), target);
00733                 SendDB("ERROR occured during saving of econ-save file");
00734                 fclose(f);
00735                 return;
00736         }
00737         fclose(f);
00738         if(i == DUMP_RESTART || i == DUMP_NORMAL) {
00739                 if(rename(target, mudconf.econ_db) < 0) {
00740                         log_perror("SAV", "FAIL", "Renaming econ-save file ", target);
00741                         SendDB("ERROR occured during renaming of econ save-file.");
00742                 }
00743         }
00744 }
00745 #endif
00746 
00747 void SaveSpecialObjects(int i)
00748 {
00749         FILE *f;
00750         int filemode, count;
00751         byte xcode_version = XCODE_VERSION;
00752         char target[LBUF_SIZE];
00753 
00754         switch (i) {
00755         case DUMP_KILLED:
00756                 sprintf(target, "%s.KILLED", mudconf.hcode_db);
00757                 break;
00758         case DUMP_CRASHED:
00759                 sprintf(target, "%s.CRASHED", mudconf.hcode_db);
00760                 break;
00761         default:                                        /* RESTART / normal */
00762                 sprintf(target, "%s.tmp", mudconf.hcode_db);
00763                 break;
00764         }
00765         f = my_open_file(target, "w", &filemode);
00766         if(!f) {
00767                 log_perror("SAV", "FAIL", "Opening new hcode-save file", target);
00768                 SendDB("ERROR occured during opening of new hcode-savefile.");
00769                 return;
00770         }
00771         fwrite(&xcode_version, 1, 1, f);
00772         count = SaveTree(f, xcode_tree);
00773         global_file_kludge = f;
00774         /* Then, check each xcode thing for stuff */
00775         GoThruTree(xcode_tree, save_maps_func);
00776 
00777         /* Save autopilot data */
00778         /* GoThruTree(xcode_tree, save_autopilot_data); */
00779 
00780         saverepairs(f);
00781         my_close_file(f, &filemode);
00782         if(i == DUMP_RESTART || i == DUMP_NORMAL) {
00783                 if(rename(mudconf.hcode_db, tprintf("%s.prev", mudconf.hcode_db))
00784                    < 0) {
00785                         log_perror("SAV", "FAIL", "Renaming old hcode-save file ",
00786                                            target);
00787                         SendDB("ERROR occured during renaming of old hcode save-file.");
00788                 }
00789                 if(rename(target, mudconf.hcode_db) < 0) {
00790                         log_perror("SAV", "FAIL", "Renaming new hcode-save file ",
00791                                            target);
00792                         SendDB("ERROR occured during renaming of new hcode save-file.");
00793                 }
00794         }
00795         if(count)
00796                 SendDB(tprintf("Hcode saved. %d xcode entries dumped.", count));
00797 #ifdef BT_ADVANCED_ECON
00798         save_econdb(target, i);
00799 #endif
00800 }
00801 
00802 static int UpdateSpecialObject_func(Node * tmp)
00803 {
00804         int i;
00805 
00806         i = WhichType(tmp);
00807         if(!SpecialObjects[i].updateTime)
00808                 return 1;
00809         if((mudstate.now % SpecialObjects[i].updateTime))
00810                 return 1;
00811         SpecialObjects[i].updatefunc(NodeKey(tmp), NodeData(tmp));
00812         return 1;
00813 }
00814 
00815 /* This is called once a second for each special object */
00816 
00817 /* Note the new handling for calls being done at <1second intervals,
00818    or possibly at >1second intervals */
00819 
00820 static time_t lastrun = 0;
00821 void UpdateSpecialObjects(void)
00822 {
00823         char *cmdsave;
00824         int i;
00825         int times = lastrun ? (mudstate.now - lastrun) : 1;
00826 
00827         if(times > 20)
00828                 times = 20;                             /* Machine's hopelessly lagged,
00829                                                                    we don't want to make it [much] worse */
00830         cmdsave = mudstate.debug_cmd;
00831         for(i = 0; i < times; i++) {
00832                 muxevent_run();
00833                 mudstate.debug_cmd = (char *) "< Generic hcode update handler>";
00834                 GoThruTree(xcode_tree, UpdateSpecialObject_func);
00835         }
00836         lastrun = mudstate.now;
00837         mudstate.debug_cmd = cmdsave;
00838 }
00839 
00840 void *NewSpecialObject(int id, int type)
00841 {
00842         void *foo;
00843         int i;
00844         dbref *t;
00845 
00846         if(SpecialObjects[type].datasize) {
00847                 Create(foo, char, (i = SpecialObjects[type].datasize));
00848 
00849                 t = (dbref *) foo;
00850                 *t = id;
00851                 if(SpecialObjects[type].allocfreefunc)
00852                         SpecialObjects[type].allocfreefunc(id, &(foo), SPECIAL_ALLOC);
00853                 AddEntry(&xcode_tree, id, type, i, foo);
00854         }
00855         return foo;
00856 }
00857 
00858 void CreateNewSpecialObject(dbref player, dbref key)
00859 {
00860         void *new;
00861         struct SpecialObjectStruct *typeOfObject;
00862         int type;
00863         char *str;
00864 
00865         str = silly_atr_get(key, A_XTYPE);
00866         if(!(str && *str)) {
00867                 notify(player,
00868                            "You must first set the XTYPE using @xtype <object>=<type>");
00869                 notify(player, "Valid XTYPEs include: MECH, MECHREP, MAP, DEBUG, "
00870                            "AUTOPILOT, TURRET.");
00871                 notify(player, "Resetting hardcode flag.");
00872                 c_Hardcode(key);                /* Reset the flag */
00873                 return;
00874         }
00875 
00876         /* Find the special objects */
00877         type = WhichSpecialS(key);
00878         if(type > -1) {
00879                 /* We found the proper special object */
00880                 typeOfObject = &SpecialObjects[type];
00881                 if(typeOfObject->datasize) {
00882                         new = NewSpecialObject(key, type);
00883                         if(!new)
00884                                 notify(player, "Memory allocation failure!");
00885                 }
00886         } else {
00887                 notify(player, "That is not a valid XTYPE!");
00888                 notify(player, "Valid XTYPEs include: MECH, MECHREP, MAP, DEBUG, "
00889                            "AUTOPILOT, TURRET.");
00890                 notify(player, "Resetting HARDCODE flag.");
00891                 c_Hardcode(key);
00892         }
00893 }
00894 
00895 void DisposeSpecialObject(dbref player, dbref key)
00896 {
00897         Node *tmp;
00898         int i;
00899         struct SpecialObjectStruct *typeOfObject;
00900 
00901         tmp = FindNode(xcode_tree, key);
00902 
00903         i = WhichSpecialS(key);
00904         if(i < 0) {
00905                 notify(player,
00906                            "CRITICAL: Unable to free data, inconsistency somewhere. Please");
00907                 notify(player, "contact a wizard about this _NOW_!");
00908                 return;
00909         }
00910         typeOfObject = &SpecialObjects[i];
00911 
00912         if(typeOfObject->datasize > 0 && WhichSpecial(key) != i) {
00913                 notify(player,
00914                            "Semi-critical error has occured. For some reason the object's data differs\nfrom the data on the object. Please contact a wizard about this.");
00915                 i = WhichSpecial(key);
00916         }
00917         if(tmp) {
00918                 void *t = NodeData(tmp);
00919 
00920                 if(typeOfObject->allocfreefunc)
00921                         typeOfObject->allocfreefunc(key, &NodeData(tmp), SPECIAL_FREE);
00922                 NodeData(tmp) = NULL;
00923                 DeleteEntry(&xcode_tree, key);  
00924                 muxevent_remove_data(t);
00925                 free(t);
00926         } else if(typeOfObject->datasize > 0) {
00927                 notify(player, "This object is not in the special object DBASE.");
00928                 notify(player, "Please contact a wizard about this bug. ");
00929         }
00930 }
00931 
00932 void Dump_Mech(dbref player, int type, char *typestr)
00933 {
00934         notify(player, "Support discontinued. Bother a wiz if this bothers you.");
00935 #if 0
00936         MECH *mech;
00937         char buff[100];
00938         int i, running = 0, count = 0;
00939         Node *temp;
00940 
00941         notify(player, "ID    # STATUS      MAP #      PILOT #");
00942         notify(player, "----------------------------------------");
00943         for(temp = TreeTop(xcode_tree); temp; temp = TreeNext(temp))
00944                 if(WhichSpecial((i = NodeKey(temp))) == type) {
00945                         mech = (MECH *) NodeData(temp);
00946                         sprintf(buff, "#%5d %-8s    #%5d    #%5d", mech->mynum,
00947                                         !Started(mech) ? "SHUTDOWN" : "RUNNING", mech->mapindex,
00948                                         MechPilot(mech));
00949                         notify(player, buff);
00950                         if(MechStatus(mech) & STARTED)
00951                                 running++;
00952                         count++;
00953                 }
00954         sprintf(buff, "%d %ss running out of %d %ss allocated.", running,
00955                         typestr, count, typestr);
00956         notify(player, buff);
00957         notify(player, "Done listing");
00958 #endif
00959 }
00960 
00961 void DumpMechs(dbref player)
00962 {
00963         Dump_Mech(player, GTYPE_MECH, "mech");
00964 }
00965 
00966 void DumpMaps(dbref player)
00967 {
00968         notify(player, "Support discontinued. Bother a wiz if this bothers you.");
00969 #if 0
00970         MAP *map;
00971         char buff[100];
00972         int j, count;
00973         Node *temp;
00974 
00975         notify(player, "MAP #       NAME              X x Y   MECHS");
00976         notify(player, "-------------------------------------------");
00977         for(temp = TreeTop(xcode_tree); temp; temp = TreeNext(temp))
00978                 if(WhichSpecial(NodeKey(temp)) == GTYPE_MAP) {
00979                         count = 0;
00980                         map = (MAP *) NodeData(temp);
00981                         for(j = 0; j < map->first_free; j++)
00982                                 if(map->mechsOnMap[j] != -1)
00983                                         count++;
00984                         sprintf(buff, "#%5d    %-17.17s %3d x%3d       %d", map->mynum,
00985                                         map->mapname, map->map_width, map->map_height, count);
00986                         notify(player, buff);
00987                 }
00988         notify(player, "Done listing");
00989 #endif
00990 }
00991 
00992 /***************** INTERNAL ROUTINES *************/
00993 #ifdef FAST_WHICHSPECIAL
00994 int WhichSpecial(dbref key)
00995 {
00996         Node *n;
00997 
00998         if(!Good_obj(key))
00999                 return -1;
01000         if(!Hardcode(key))
01001                 return -1;
01002         if(!(n = FindObjectsNode(key)))
01003                 return -1;
01004         return NodeType(n);
01005 }
01006 
01007 #endif
01008 
01009 #ifdef FAST_WHICHSPECIAL
01010 static int WhichSpecialS(dbref key)
01011 #else
01012 int WhichSpecial(dbref key)
01013 #endif
01014 {
01015         int i;
01016         int returnValue = -1;
01017         char *str;
01018 
01019         if(!Hardcode(key))
01020                 return -1;
01021         str = silly_atr_get(key, A_XTYPE);
01022         if(str && *str) {
01023                 for(i = 0; i < NUM_SPECIAL_OBJECTS; i++) {
01024                         if(!strcmp(SpecialObjects[i].type, str)) {
01025                                 returnValue = i;
01026                                 break;
01027                         }
01028                 }
01029         }
01030         return (returnValue);
01031 }
01032 
01033 int IsMech(dbref num)
01034 {
01035         return WhichSpecial(num) == GTYPE_MECH;
01036 }
01037 
01038 int IsAuto(dbref num)
01039 {
01040         return WhichSpecial(num) == GTYPE_AUTO;
01041 }
01042 
01043 int IsMap(dbref num)
01044 {
01045         return WhichSpecial(num) == GTYPE_MAP;
01046 }
01047 
01048 /*** Support routines ***/
01049 static Node *FindObjectsNode(dbref key)
01050 {
01051         Node *tmp;
01052 
01053         if((tmp = FindNode(xcode_tree, (int) key)))
01054                 return tmp;
01055         return NULL;
01056 }
01057 
01058 void *FindObjectsData(dbref key)
01059 {
01060         Node *tmp;
01061 
01062         if((tmp = FindObjectsNode(key)))
01063                 return NodeData(tmp);
01064         return NULL;
01065 }
01066 
01067 char *center_string(char *c, int len)
01068 {
01069         static char buf[LBUF_SIZE];
01070         int l = strlen(c);
01071         int p, i;
01072 
01073         p = MAX(0, (len - l) / 2);
01074         for(i = 0; i < p; i++)
01075                 buf[i] = ' ';
01076         strcpy(buf + p, c);
01077         return buf;
01078 }
01079 
01080 static void help_color_initialize(char *from, char *to)
01081 {
01082         int i;
01083         char buf[LBUF_SIZE];
01084 
01085         for(i = 0; from[i] && from[i] != ' '; i++);
01086         if(from[i]) {
01087 
01088                 /*      from[i]=0; */
01089                 strncpy(buf, from, i);
01090                 buf[i] = 0;
01091                 sprintf(to, "%s%s%s %s", "%ch%cb", buf, "%cn", &from[i + 1]);
01092 
01093                 /*      from[i]=' '; */
01094         } else
01095                 sprintf(to, "%s%s%s", "%cc", from, "%cn");
01096 
01097 }
01098 
01099 #define ONE_LINE_TEXTS
01100 
01101 #ifdef ONE_LINE_TEXTS
01102 #define MLen CM_ONE
01103 #else
01104 #define MLen CM_TWO
01105 #endif
01106 
01107 static char *do_ugly_things(coolmenu ** d, char *msg, int len, int initial)
01108 {
01109         coolmenu *c = *d;
01110         char *e;
01111         int i;
01112         char buf[LBUF_SIZE];
01113         char msg2[LBUF_SIZE];
01114 
01115         strcpy(msg2, msg);
01116 #ifndef ONE_LINE_TEXTS
01117         if(!msg) {
01118                 sim(" ", MLen);
01119                 *d = c;
01120                 return NULL;
01121         }
01122 #endif
01123         if(strlen(msg) < len) {
01124                 if(initial) {
01125                         if(initial > 0)
01126                                 help_color_initialize(msg, buf);
01127                         else {
01128                                 for(i = 0; i < -initial; i++)
01129                                         buf[i] = ' ';
01130                                 strcpy(&buf[i], msg);
01131                         }
01132                         sim(buf, MLen);
01133                 } else
01134                         sim(msg, MLen);
01135                 *d = c;
01136                 return NULL;
01137         }
01138         for(e = msg2 + len - 1; *e != ' '; e--);
01139         *e = 0;
01140         if(initial) {
01141                 if(initial > 0)
01142                         help_color_initialize(msg2, buf);
01143                 else {
01144                         for(i = 0; i < -initial; i++)
01145                                 buf[i] = ' ';
01146                         strcpy(&buf[i], msg2);
01147                 }
01148                 sim(buf, MLen);
01149         } else
01150                 sim(msg2, MLen);
01151         *e = ' ';
01152         *d = c;
01153         if((*e + 1))
01154                 return e + 1;
01155         return NULL;
01156 }
01157 
01158 #define Len(s) ((!s || !*s) ? 0 : strlen(s))
01159 
01160 #define TAB 3
01161 
01162 static void cut_apart_helpmsgs(coolmenu ** d, char *msg1, char *msg2,
01163                                                            int len, int initial)
01164 {
01165         int l1 = Len(msg1);
01166         int l2 = Len(msg2);
01167         int nl1, nl2;
01168 
01169 #ifndef ONE_LINE_TEXTS
01170 
01171         msg1 = do_ugly_things(d, msg1, len, initial);
01172         msg2 =
01173                 do_ugly_things(d, msg2, initial ? len : len - TAB,
01174                                            initial ? 0 : 0 - TAB);
01175         if(!msg1 && !msg2)
01176                 return;
01177         nl1 = Len(msg1);
01178         nl2 = Len(msg2);
01179         if(nl1 != l1 || nl2 != l2)      /* To prevent infinite loops */
01180                 cut_apart_helpmsgs(d, msg1, msg2, len, 0);
01181 #else
01182         int first = 1;
01183 
01184         while (msg1 && *msg1) {
01185                 msg1 = do_ugly_things(d, msg1, len * 2 - 1, first);
01186                 nl1 = Len(msg1);
01187                 if(nl1 == l1)
01188                         break;
01189                 l1 = nl1;
01190                 first = 0;
01191         }
01192         while (msg2 && *msg2) {
01193                 msg2 = do_ugly_things(d, msg2, len * 2 - TAB, 0 - TAB);
01194                 nl2 = Len(msg2);
01195                 if(nl2 == l2)
01196                         break;
01197                 l2 = nl2;
01198         }
01199 
01200 #endif
01201 }
01202 
01203 static void DoSpecialObjectHelp(dbref player, char *type, int id, int loc,
01204                                                                 int powerneeded, int objid, char *arg)
01205 {
01206         int i, j;
01207         MECH *mech = NULL;
01208         int pos[100][2];
01209         int count = 0, csho = 0;
01210         coolmenu *c = NULL;
01211         char buf[LBUF_SIZE];
01212         char *d;
01213         int dc;
01214 
01215         if(id == GTYPE_MECH)
01216                 mech = getMech(loc);
01217         bzero(pos, sizeof(pos));
01218         for(i = 0; SpecialObjects[id].commands[i].name; i++) {
01219                 if(!SpecialObjects[id].commands[i].func &&
01220                    (SpecialObjects[id].commands[i].helpmsg[0] != '@' ||
01221                         Have_MechPower(Owner(player), powerneeded)))
01222                         if(id != GTYPE_MECH ||
01223                            Can_Use_Command(mech, SpecialObjects[id].commands[i].flag)) {
01224                                 if(count)
01225                                         pos[count - 1][1] = i - pos[count - 1][0];
01226                                 pos[count][0] = i;
01227                                 count++;
01228                         }
01229         }
01230         if(count)
01231                 pos[count - 1][1] = i - pos[count - 1][0];
01232         else {
01233                 pos[0][0] = 0;
01234                 pos[0][1] = i;
01235                 count = 1;
01236         }
01237         sim(NULL, CM_ONE | CM_LINE);
01238         if(!arg || !*arg) {
01239 #define HELPMSG(a) \
01240         &SpecialObjects[id].commands[a].helpmsg[SpecialObjects[id].commands[a].helpmsg[0]=='@']
01241                 for(i = 0; i < count; i++) {
01242                         if(count > 1) {
01243                                 d = center_string(HELPMSG(pos[i][0]), 70);
01244                                 sim(tprintf("%s%s%s", "%cg", d, "%c"), CM_ONE);
01245                         } else
01246                                 sim(tprintf("%s command listing: ", type),
01247                                         CM_ONE | CM_CENTER);
01248                         for(j = pos[i][0] + (count == 1 ? 0 : 1);
01249                                 j < pos[i][0] + pos[i][1]; j++)
01250                                 if(SpecialObjects[id].commands[j].helpmsg[0] != '@' ||
01251                                    Have_MechPower(Owner(player), powerneeded))
01252                                         if(id != GTYPE_MECH ||
01253                                            Can_Use_Command(mech,
01254                                                                            SpecialObjects[id].commands[j].flag)) {
01255                                                 strcpy(buf, SpecialObjects[id].commands[j].name);
01256                                                 d = buf;
01257                                                 while (*d && *d != ' ')
01258                                                         d++;
01259                                                 if(*d == ' ')
01260                                                         *d = 0;
01261                                                 sim(buf, CM_FOUR);
01262                                                 csho++;
01263                                         }
01264                 }
01265                 if(!csho)
01266                         vsi(tprintf
01267                                 ("There are no commands you are authorized to use here."));
01268                 else {
01269                         sim(NULL, CM_ONE | CM_LINE);
01270                         if(count > 1)
01271                                 vsi("Additional info available with 'HELP SUBTOPIC'");
01272                         else
01273                                 vsi("Additional info available with 'HELP ALL'");
01274                 }
01275         } else {
01276                 /* Try to find matching subtopic, or ALL */
01277                 if(!strcasecmp(arg, "all")) {
01278                         if(count > 1) {
01279                                 vsi("ALL not available for objects with subcategories.");
01280                                 dc = -2;
01281                         } else
01282                                 dc = -1;
01283                 } else {
01284                         if(count == 1) {
01285                                 vsi("This object doesn't have any other detailed help than 'HELP ALL'");
01286                                 dc = -2;
01287                         } else {
01288                                 for(i = 0; i < count; i++)
01289                                         if(!strcasecmp(arg, HELPMSG(pos[i][0])))
01290                                                 break;
01291                                 if(i == count) {
01292                                         vsi("Subcategory not found.");
01293                                         dc = -2;
01294                                 } else
01295                                         dc = i;
01296                         }
01297                 }
01298                 if(dc > -2) {
01299                         for(i = 0; i < count; i++)
01300                                 if(dc == -1 || i == dc) {
01301                                         if(count > 1)
01302                                                 vsi(tprintf("%s%s%s", "%cg",
01303                                                                         center_string(HELPMSG(pos[i][0]), 70),
01304                                                                         "%c"));
01305                                         for(j = pos[i][0] + (count == 1 ? 0 : 1);
01306                                                 j < pos[i][0] + pos[i][1]; j++)
01307                                                 if(SpecialObjects[id].commands[j].helpmsg[0] !=
01308                                                    '@' || Have_MechPower(Owner(player), powerneeded))
01309                                                         if(id != GTYPE_MECH ||
01310                                                            Can_Use_Command(mech,
01311                                                                                            SpecialObjects[id].commands[j].
01312                                                                                            flag))
01313                                                                 cut_apart_helpmsgs(&c,
01314                                                                                                    SpecialObjects[id].
01315                                                                                                    commands[j].name,
01316                                                                                                    HELPMSG(j), 37, 1);
01317                                 }
01318                 }
01319         }
01320         sim(NULL, CM_ONE | CM_LINE);
01321         ShowCoolMenu(player, c);
01322         KillCoolMenu(c);
01323 }
01324 
01325 void InitSpecialHash(int which)
01326 {
01327         char *tmp, *tmpc;
01328         int i;
01329         char buf[MBUF_SIZE];
01330 
01331         hashinit(&SpecialCommandHash[which], 20 * HASH_FACTOR);
01332         for(i = 0; (tmp = SpecialObjects[which].commands[i].name); i++) {
01333                 if(!SpecialObjects[which].commands[i].func)
01334                         continue;
01335                 tmpc = buf;
01336                 for(; *tmp && *tmp != ' '; tmp++)
01337                         *(tmpc++) = ToLower(*tmp);
01338                 *tmpc = 0;
01339                 if((tmpc = strstr(buf, " ")))
01340                         *tmpc = 0;
01341                 hashadd(buf, (int *) &SpecialObjects[which].commands[i],
01342                                 &SpecialCommandHash[which]);
01343         }
01344 }
01345 
01346 void handle_xcode(dbref player, dbref obj, int from, int to)
01347 {
01348         if(from == to)
01349                 return;
01350         if(!to) {
01351                 s_Hardcode(obj);
01352                 DisposeSpecialObject(player, obj);
01353                 c_Hardcode(obj);
01354         } else
01355                 CreateNewSpecialObject(player, obj);
01356 }
01357 
01358 #define DEFAULT 0                               /* Normal */
01359 #define ANSI_START "\033["
01360 #define ANSI_START_LEN 2
01361 #define ANSI_END "m"
01362 #define ANSI_END_LEN 1
01363 
01364 struct color_entry {
01365         int bit;
01366         int negbit;
01367         char ltr;
01368         char *string;
01369         char *sstring;
01370 } color_table[] = {
01371         {
01372         0x0008, 7, 'n', ANSI_NORMAL, NULL}, {
01373         0x0001, 0, 'h', ANSI_HILITE, NULL}, {
01374         0x0002, 0, 'i', ANSI_INVERSE, NULL}, {
01375         0x0004, 0, 'f', ANSI_BLINK, NULL}, {
01376         0x0010, 0, 'x', ANSI_BLACK, NULL}, {
01377         0x0010, 0x10, 'l', ANSI_BLACK, NULL}, {
01378         0x0020, 0, 'r', ANSI_RED, NULL}, {
01379         0x0040, 0, 'g', ANSI_GREEN, NULL}, {
01380         0x0080, 0, 'y', ANSI_YELLOW, NULL}, {
01381         0x0100, 0, 'b', ANSI_BLUE, NULL}, {
01382         0x0200, 0, 'm', ANSI_MAGENTA, NULL}, {
01383         0x0400, 0, 'c', ANSI_CYAN, NULL}, {
01384         0x0800, 0, 'w', ANSI_WHITE, NULL}, {
01385         0, 0, 0, NULL, NULL}
01386 };
01387 
01388 #define CHARS 256
01389 
01390 char colorc_reverse[CHARS];
01391 
01392 void initialize_colorize()
01393 {
01394         int i;
01395         char buf[20];
01396         char *c;
01397 
01398         c = buf + ANSI_START_LEN;
01399         for(i = 0; i < CHARS; i++)
01400                 colorc_reverse[i] = DEFAULT;
01401         for(i = 0; color_table[i].string; i++) {
01402                 colorc_reverse[(short) color_table[i].ltr] = i;
01403                 strcpy(buf, color_table[i].string);
01404                 buf[strlen(buf) - ANSI_END_LEN] = 0;
01405                 color_table[i].sstring = strdup(c);
01406         }
01407 
01408 }
01409 
01410 #undef notify
01411 char *colorize(dbref player, char *from)
01412 {
01413         char *to;
01414         char *p, *q;
01415         int color_wanted = 0;
01416         int i;
01417         int cnt;
01418 
01419         q = to = alloc_lbuf("colorize");
01420 #if 1
01421         for(p = from; *p; p++) {
01422                 if(*p == '%' && *(p + 1) == 'c') {
01423                         p += 2;
01424                         if(*p <= 0)
01425                                 i = DEFAULT;
01426                         else
01427                                 i = colorc_reverse[(short) *p];
01428                         if(i == DEFAULT && *p != 'n')
01429                                 p--;
01430                         color_wanted &= ~color_table[i].negbit;
01431                         color_wanted |= color_table[i].bit;
01432                 } else {
01433                         if(color_wanted && Ansi(player)) {
01434                                 *q = 0;
01435                                 /* Generate efficient color string */
01436                                 strcpy(q, ANSI_START);
01437                                 q += ANSI_START_LEN;
01438                                 cnt = 0;
01439                                 for(i = 0; color_table[i].string; i++)
01440                                         if(color_wanted & color_table[i].bit &&
01441                                            color_table[i].bit != color_table[i].negbit) {
01442                                                 if(cnt)
01443                                                         *q++ = ';';
01444                                                 strcpy(q, color_table[i].sstring);
01445                                                 q += strlen(color_table[i].sstring);
01446                                                 cnt++;
01447                                         }
01448                                 strcpy(q, ANSI_END);
01449                                 q += ANSI_END_LEN;
01450                                 color_wanted = 0;
01451                         }
01452                         *q++ = *p;
01453                 }
01454         }
01455         *q = 0;
01456         if(color_wanted && Ansi(player)) {
01457                 /* Generate efficient color string */
01458                 strcpy(q, ANSI_START);
01459                 q += ANSI_START_LEN;
01460                 cnt = 0;
01461                 for(i = 0; color_table[i].string; i++)
01462                         if(color_wanted & color_table[i].bit &&
01463                            color_table[i].bit != color_table[i].negbit) {
01464                                 if(cnt)
01465                                         *q++ = ';';
01466                                 strcpy(q, color_table[i].sstring);
01467                                 q += strlen(color_table[i].sstring);
01468                                 cnt++;
01469                         }
01470                 strcpy(q, ANSI_END);
01471                 q += ANSI_END_LEN;
01472                 color_wanted = 0;
01473         }
01474 #else
01475         strcpy(to, p);
01476 #endif
01477         return to;
01478 }
01479 
01480 void mecha_notify(dbref player, char *msg)
01481 {
01482         char *tmp;
01483 
01484         tmp = colorize(player, msg);
01485         raw_notify(player, tmp);
01486         free_lbuf(tmp);
01487 }
01488 
01489 void mecha_notify_except(dbref loc, dbref player, dbref exception, char *msg)
01490 {
01491         dbref first;
01492 
01493         if(loc != exception)
01494                 notify_checked(loc, player, msg,
01495                                            (MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A
01496                                                 | MSG_COLORIZE));
01497         DOLIST(first, Contents(loc)) {
01498                 if(first != exception) {
01499                         notify_checked(first, player, msg,
01500                                                    (MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE |
01501                                                         MSG_COLORIZE));
01502                 }
01503         }
01504 }
01505 
01506 /* 
01507    Basically, finish all the repairs etc in one fell swoop. That's the
01508    best we can do for now, I'm afraid. 
01509    */
01510 void ResetSpecialObjects()
01511 {
01512 #if 0                                                   /* Nowadays no longer neccessary, see mech.tech.saverepair.c */
01513         int i;
01514 
01515         for(i = FIRST_TECH_EVENT; i <= LAST_TECH_EVENT; i++)
01516                 while (muxevent_run_by_type(i));
01517 #endif
01518         muxevent_run_by_type(EVENT_HIDE);
01519         muxevent_run_by_type(EVENT_BLINDREC);
01520 }
01521 
01522 MAP *getMap(dbref d)
01523 {
01524         Node *tmp;
01525 
01526         if(!(tmp = FindObjectsNode(d)))
01527                 return NULL;
01528         if(NodeType(tmp) != GTYPE_MAP)
01529                 return NULL;
01530         return (MAP *) NodeData(tmp);
01531 }
01532 
01533 MECH *getMech(dbref d)
01534 {
01535         Node *tmp;
01536 
01537         if(!(Good_obj(d)))
01538                 return NULL;
01539         if(!(Hardcode(d)))
01540                 return NULL;
01541         if(!(tmp = FindObjectsNode(d)))
01542                 return NULL;
01543         if(NodeType(tmp) != GTYPE_MECH)
01544                 return NULL;
01545         return (MECH *) NodeData(tmp);
01546 }

Generated on Mon May 28 04:25:24 2007 for BattletechMUX by  doxygen 1.4.7