/* * $Id: econ_cmds.c,v 1.1.1.1 2005/01/11 21:18:06 kstevens Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1996 Markus Stenberg * Copyright (c) 1998-2002 Thomas Wouters * Copyright (c) 2000-2002 Cord Awtry * Copyright (c) 1999-2005 Kevin Stevens * All rights reserved * * Created: Sat Oct 5 14:31:07 1996 fingon * Last modified: Sun Jun 14 14:53:05 1998 fingon * */ /* This is the place for - loadcargo - unloadcargo - manifest - stores */ #include <stdio.h> #include "mech.h" #include "coolmenu.h" #include "math.h" #include "mech.partnames.h" #include "p.aero.bomb.h" #include "p.econ.h" #include "p.mech.partnames.h" #include "p.crit.h" #include "p.mech.status.h" #include "p.mech.utils.h" #ifdef BT_PART_WEIGHTS /* From template.c */ extern int internalsweight[]; extern int cargoweight[]; #endif /* BT_PART_WEIGHTS */ /* Also sets the fuel we have ; but I digress */ void SetCargoWeight(MECH * mech) { int pile[NUM_ITEMS]; int sw, weight = 0; /* in 1/10 tons */ int i, j, k; char *t; int i1, i2, i3; t = silly_atr_get(mech->mynum, A_ECONPARTS); bzero(pile, sizeof(pile)); while (*t) { if (*t == '[') if ((sscanf(t, "[%d,%d,%d]", &i1, &i2, &i3)) == 3) pile[i1] += ((IsBomb(i1)) ? 4 : 1) * i3; t++; } if (FlyingT(mech)) for (i = 0; i < NUM_SECTIONS; i++) for (j = 0; j < NUM_CRITICALS; j++) { if (IsBomb((k = GetPartType(mech, i, j)))) pile[k]++; else if (IsSpecial(k)) if (Special2I(k) == FUELTANK) pile[I2Special(FUELTANK)]++; } /* We've 'so-called' pile now */ for (i = 0; i < NUM_ITEMS; i++) if (pile[i]) { sw = GetPartWeight(i); weight += sw * pile[i]; } if (FlyingT(mech)) { AeroFuelMax(mech) = AeroFuelOrig(mech) + 2000 * pile[I2Special(FUELTANK)]; if (AeroFuel(mech) > AeroFuelOrig(mech)) weight += AeroFuel(mech) - AeroFuelOrig(mech); } SetCarriedCargo(mech, weight); } /* Returns 1 if calling function should return */ int loading_bay_whine(dbref player, dbref cargobay, MECH * mech) { char *c; int i1, i2, i3 = 0; c = silly_atr_get(cargobay, A_MECHSKILLS); if (c && *c) if (sscanf(c, "%d %d %d", &i1, &i2, &i3) >= 2) if (MechX(mech) != i1 || MechY(mech) != i2) { notify(player, "You're not where the cargo is!"); if (i3) notify(player, tprintf("Try looking around %d,%d instead.", i1, i2)); return 1; } return 0; } void mech_Rfixstuff(dbref player, void *data, char *buffer) { int loc = Location(player); int pile[BRANDCOUNT + 1][NUM_ITEMS]; char *t; int ol, nl, items = 0, kinds = 0; int i1, i2, i3, id, brand; if (!data) loc = atoi(buffer); bzero(pile, sizeof(pile)); t = silly_atr_get(loc, A_ECONPARTS); ol = strlen(t); while (*t) { if (*t == '[') if ((sscanf(t, "[%d,%d,%d]", &i1, &i2, &i3)) == 3) if (!IsCrap(i1)) pile[i2][i1] += i3; t++; } silly_atr_set(loc, A_ECONPARTS, ""); for (id = 0; id < NUM_ITEMS; id++) for (brand = 0; brand <= BRANDCOUNT; brand++) if (pile[brand][id] > 0 && get_parts_long_name(id, brand)) { econ_change_items(loc, id, brand, pile[brand][id]); kinds++; items += pile[brand][id]; } t = silly_atr_get(loc, A_ECONPARTS); nl = strlen(t); notify(player, tprintf("Fixing done. Original length: %d. New length: %d.", ol, nl)); notify(player, tprintf("Items in new: %d. Unique items in new: %d.", items, kinds)); } void list_matching(dbref player, char *header, dbref loc, char *buf) { int pile[BRANDCOUNT + 1][NUM_ITEMS]; int pile2[BRANDCOUNT + 1][NUM_ITEMS]; char *t, *ch; int i1, i2, i3, id, brand; int x, i; #ifdef BT_PART_WEIGHTS char tmpstr[LBUF_SIZE]; int sw = 0; #endif /* BT_PART_WEIGHTS */ coolmenu *c = NULL; int found = 0; bzero(pile, sizeof(pile)); bzero(pile2, sizeof(pile2)); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); CreateMenuEntry_Simple(&c, header, CM_ONE | CM_CENTER); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); /* Then, we go on a mad rampage ;-) */ t = silly_atr_get(loc, A_ECONPARTS); while (*t) { if (*t == '[') if ((sscanf(t, "[%d,%d,%d]", &i1, &i2, &i3)) == 3) pile[i2][i1] += i3; t++; } i = 0; if (buf) while (find_matching_long_part(buf, &i, &id, &brand)) pile2[brand][id] = pile[brand][id]; for (i = 0; i < object_count; i++) { UNPACK_PART(short_sorted[i]->index, id, brand); if ((buf && (x = pile2[brand][id])) || ((!buf && (x = pile[brand][id])))) { #ifndef BT_PART_WEIGHTS ch = part_name_long(id, brand); #else sw = GetPartWeight(id); sprintf(tmpstr, "%s (%.1ft)", part_name_long(id, brand), (sw * x) / 1024.0); ch = tmpstr; #endif /* BT_PART_WEIGHTS */ if (!ch) { SendError(tprintf ("#%d in %d encountered odd thing: %d %d/%d's.", player, loc, pile[brand][id], id, brand)); continue; } /* x = amount of things */ CreateMenuEntry_Killer(&c, ch, CM_TWO | CM_NUMBER | CM_NOTOG, 0, x, x); found++; } } if (!found) CreateMenuEntry_Simple(&c, "None", CM_ONE); CreateMenuEntry_Simple(&c, NULL, CM_ONE | CM_LINE); ShowCoolMenu(player, c); KillCoolMenu(c); } #define MY_DO_LIST(t) \ if (*buffer) \ list_matching(player, tprintf("Part listing for %s matching %s", Name(t), buffer), t, buffer); \ else \ list_matching(player, tprintf("Part listing for %s", Name(t)), t, NULL) void mech_manifest(dbref player, void *data, char *buffer) { while (isspace(*buffer)) buffer++; MY_DO_LIST(Location(player)); } void mech_stores(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUAL); DOCHECK(Location(mech->mynum) != mech->mapindex || In_Character(Location(mech->mynum)), "You aren't inside a hangar!"); if (loading_bay_whine(player, Location(mech->mynum), mech)) return; while (isspace(*buffer)) buffer++; MY_DO_LIST(Location(mech->mynum)); } #ifdef ECON_ALLOW_MULTIPLE_LOAD_UNLOAD #define silly_search(func) \ if (!count) { \ i = -1 ; while (func(args[0], &i, &id, &brand)) \ count++; \ if (count > 0) sfun = func; } #else #define silly_search(func) \ if (!count) { \ i = -1 ; while (func(args[0], &i, &id, &brand)) \ count++; \ DOCHECK(count > 1, "Too many matches!"); \ if (count > 0) sfun = func; } #endif /* Handles adding or removing parts/commods from a map or unit's manifest. * btaddstores(), addstuff, and removestuff use this. */ static void stuff_change_sub(dbref player, char *buffer, dbref loc1, dbref loc2, int mod, int mort) { int i = -1, id, brand; int count = 0; int argc; char *args[2]; char *c; int num; int (*sfun) (char *, int *i, int *id, int *brand) = NULL; int foo = 0; argc = mech_parseattributes(buffer, args, 2); DOCHECK(argc < 2, "Invalid number of arguments!"); /* * If we hit the max amount of parts addable at once, set quantity * to add to max. */ num = atoi(args[1]); if (num > ADDSTORES_MAX) { num = ADDSTORES_MAX; } DOCHECK(num <= 0, "Invalid amount!"); silly_search(find_matching_short_part); silly_search(find_matching_vlong_part); silly_search(find_matching_long_part); DOCHECK(count == 0, tprintf("Nothing matches '%s'!", args[0])); DOCHECK(!mort && count > 20 && player != GOD, tprintf ("Wizards can't add more than 20 different objtypes at a time. ('%s' matches: %d)", args[0], count)); if (mort) { DOCHECK(Location(player) != loc1, "You ain't in your 'mech!"); DOCHECK(Location(loc1) != loc2, "You ain't in hangar!"); } i = -1; #define MY_ECON_MODIFY(loc,num) \ econ_change_items(loc, id, brand, num); \ SendEcon(tprintf("#%d %s %d %s %s #%d.", \ player, num>0 ? "added": "removed", \ abs(num), (c=get_parts_long_name(id,brand)), \ num>0 ? "to": "from", \ loc)) while (sfun(args[0], &i, &id, &brand)) { if (mort) { if (mod < 0) count = MIN(num, econ_find_items(loc1, id, brand)); else count = MIN(num, econ_find_items(loc2, id, brand)); } else count = num; foo += count; if (!count) continue; MY_ECON_MODIFY(loc1, mod * count); if (count) switch (mort) { case 0: notify(player, tprintf("You %s %d %s%s.", mod > 0 ? "add" : "remove", count, c, count > 1 ? "s" : "")); break; case 1: MY_ECON_MODIFY(loc2, (0 - mod) * count); notify(player, tprintf("You %s %d %s%s.", mod > 0 ? "load" : "unload", count, c, count > 1 ? "s" : "")); break; } } DOCHECK(!foo, "Nothing matching that criteria was found!"); } void mech_Raddstuff(dbref player, void *data, char *buffer) { stuff_change_sub(player, buffer, Location(player), -1, 1, 0); } void mech_Rremovestuff(dbref player, void *data, char *buffer) { stuff_change_sub(player, buffer, Location(player), -1, -1, 0); } void mech_loadcargo(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALO); DOCHECK(!(MechSpecials(mech) & CARGO_TECH), "This unit cannot haul cargo!"); DOCHECK(fabs(MechSpeed(mech)) > 0.0, "You're moving too fast!"); DOCHECK(Location(mech->mynum) != mech->mapindex || In_Character(Location(mech->mynum)), "You aren't inside hangar!"); if (loading_bay_whine(player, Location(mech->mynum), mech)) return; stuff_change_sub(player, buffer, mech->mynum, mech->mapindex, 1, 1); correct_speed(mech); } void mech_unloadcargo(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALSO); DOCHECK(!(MechSpecials(mech) & CARGO_TECH), "This unit cannot haul cargo!"); stuff_change_sub(player, buffer, mech->mynum, mech->mapindex, -1, 1); correct_speed(mech); } void mech_Rresetstuff(dbref player, void *data, char *buffer) { notify(player, "Inventory cleaned!"); silly_atr_set(Location(player), A_ECONPARTS, ""); SendEcon(tprintf("#%d reset #%d's stuff.", player, Location(player))); }