/* * $Id: mech.advanced.c,v 1.3 2005/06/23 18:31:42 av1-op Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1996 Markus Stenberg * Copyright (c) 1998-2002 Thomas Wouters * Copyright (c) 2000-2002 Cord Awtry * All rights reserved * * Last modified: Tue Sep 8 10:12:37 1998 fingon * * Complete rewrite of the original MUSE code (because original sucked) * */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <sys/file.h> #include "mech.h" #include "mech.events.h" #include "coolmenu.h" #include "p.mech.ecm.h" #include "mech.ecm.h" #include "p.mech.utils.h" #include "p.mech.update.h" #include "p.mech.combat.h" #include "p.mech.damage.h" #include "p.artillery.h" #include "p.btechstats.h" #include "failures.h" #include "p.crit.h" #include "p.mech.build.h" #include "p.mech.hitloc.h" #include "p.mech.enhanced.criticals.h" #include "p.mech.combat.misc.h" #define SILLY_TOGGLE_MACRO(neededspecial,setstatus,msgon,msgoff,donthave) \ if (MechSpecials(mech) & (neededspecial)) \ { if (MechStatus(mech) & (setstatus)) { mech_notify(mech, MECHALL, msgoff); \ MechStatus(mech) &= ~(setstatus); } else { mech_notify(mech,MECHALL, msgon); \ MechStatus(mech) |= (setstatus); } } else notify(player, donthave) #define TOGGLE_SPECIALS_MACRO_CHECK(neededspecial,setstatus,offstatus,msgon,msgoff,donthave) \ if (MechSpecials(mech) & (neededspecial)) \ { if (MechStatus2(mech) & (setstatus)) { mech_notify(mech, MECHALL, msgoff); \ MechStatus2(mech) &= ~(setstatus); } else { mech_notify(mech,MECHALL, msgon); \ MechStatus2(mech) |= (setstatus); MechStatus2(mech) &= ~(offstatus); } } else notify(player, donthave) #define TOGGLE_SPECIALS_MACRO_CHECK2(neededspecial,setstatus,offstatus,msgon,msgoff,donthave) \ if (MechSpecials2(mech) & (neededspecial)) \ { if (MechStatus2(mech) & (setstatus)) { mech_notify(mech, MECHALL, msgoff); \ MechStatus2(mech) &= ~(setstatus); } else { mech_notify(mech,MECHALL, msgon); \ MechStatus2(mech) |= (setstatus); MechStatus2(mech) &= ~(offstatus); } } else notify(player, donthave) #define TOGGLE_INFANTRY_MACRO_CHECK(neededspecial,setstatus,offstatus,msgon,msgoff,donthave) \ if (MechInfantrySpecials(mech) & (neededspecial)) \ { if (MechStatus2(mech) & (setstatus)) { mech_notify(mech, MECHALL, msgoff); \ MechStatus2(mech) &= ~(setstatus); } else { mech_notify(mech,MECHALL, msgon); \ MechStatus2(mech) |= (setstatus); MechStatus2(mech) &= ~(offstatus); } } else notify(player, donthave) static void mech_toggle_mode_sub(dbref player, MECH * mech, char *buffer, int nspecisspec, int nspec, int mode, int tFireMode, char *onmsg, char *offmsg, char *cant); /* Toggles ECM on / off */ void mech_ecm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); DOCHECK(MechCritStatus(mech) & ECM_DESTROYED, "Your Guardian ECM has been destroyed already!"); TOGGLE_SPECIALS_MACRO_CHECK(ECM_TECH, ECM_ENABLED, ECCM_ENABLED, "You turn your ECM suite online (ECM mode).", "You turn your ECM suite offline.", "This unit isn't equipped with an ECM suite!"); MarkForLOSUpdate(mech); } void mech_eccm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); DOCHECK(MechCritStatus(mech) & ECM_DESTROYED, "Your Guardian ECM has been destroyed already!"); TOGGLE_SPECIALS_MACRO_CHECK(ECM_TECH, ECCM_ENABLED, ECM_ENABLED, "You turn your ECM suite online (ECCM mode).", "You turn your ECM suite offline.", "This unit isn't equipped with an ECM suite!"); MarkForLOSUpdate(mech); } void mech_perecm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); TOGGLE_INFANTRY_MACRO_CHECK(FC_INFILTRATORII_STEALTH_TECH, PER_ECM_ENABLED, PER_ECCM_ENABLED, "You turn your Personal ECM suite online (ECM mode).", "You turn your Personal ECM suite offline.", "This unit isn't equipped with a Personal ECM suite!"); MarkForLOSUpdate(mech); } void mech_pereccm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); TOGGLE_INFANTRY_MACRO_CHECK(FC_INFILTRATORII_STEALTH_TECH, PER_ECCM_ENABLED, PER_ECM_ENABLED, "You turn your Personal ECM suite online (ECCM mode).", "You turn your Personal ECM suite offline.", "This unit isn't equipped with a Personal ECM suite!"); MarkForLOSUpdate(mech); } void mech_angelecm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); DOCHECK(MechCritStatus(mech) & ANGEL_ECM_DESTROYED, "Your Angel ECM has been destroyed already!"); TOGGLE_SPECIALS_MACRO_CHECK2(ANGEL_ECM_TECH, ANGEL_ECM_ENABLED, ANGEL_ECCM_ENABLED, "You turn your Angel ECM suite online (ECM mode).", "You turn your Angel ECM suite offline.", "This unit isn't equipped with an Angel ECM suite!"); MarkForLOSUpdate(mech); } void mech_angeleccm(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); DOCHECK(MechCritStatus(mech) & ANGEL_ECM_DESTROYED, "Your Angel ECM has been destroyed already!"); TOGGLE_SPECIALS_MACRO_CHECK2(ANGEL_ECM_TECH, ANGEL_ECCM_ENABLED, ANGEL_ECM_ENABLED, "You turn your Angel ECM suite online (ECCM mode).", "You turn your Angel ECM suite offline.", "This unit isn't equipped with an Angel ECM suite!"); MarkForLOSUpdate(mech); } void MechSliteChangeEvent(MUXEVENT * e) { MECH *mech = (MECH *) e->data; int wType = (int) e->data2; if (MechCritStatus(mech) & SLITE_DEST) return; if (!Started(mech)) return; if (!Started(mech)) { MechStatus2(mech) &= ~SLITE_ON; MechCritStatus(mech) &= ~SLITE_LIT; return; } if (wType == 1) { MechStatus2(mech) |= SLITE_ON; MechCritStatus(mech) |= SLITE_LIT; mech_notify(mech, MECHALL, "Your searchlight comes on to full power."); MechLOSBroadcast(mech, "turns on a searchlight!"); } else { MechStatus2(mech) &= ~SLITE_ON; MechCritStatus(mech) &= ~SLITE_LIT; mech_notify(mech, MECHALL, "Your searchlight shuts off."); MechLOSBroadcast(mech, "turns off a searchlight!"); } MarkForLOSUpdate(mech); } void mech_slite(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); if (!(MechSpecials(mech) & SLITE_TECH)) { mech_notify(mech, MECHALL, "Your 'mech isn't equipped with searchlight!"); return; } DOCHECK(MechCritStatus(mech) & SLITE_DEST, "Your searchlight has been destroyed already!"); if (SearchlightChanging(mech)) { if (MechStatus2(mech) & SLITE_ON) mech_notify(mech, MECHALL, "Your searchlight is already in the process of turning off."); else mech_notify(mech, MECHALL, "Your searchlight is already in the process of turning on."); return; } if (MechStatus2(mech) & SLITE_ON) { mech_notify(mech, MECHALL, "Your searchlight starts to cool down."); MECHEVENT(mech, EVENT_SLITECHANGING, MechSliteChangeEvent, 5, 0); } else { mech_notify(mech, MECHALL, "Your searchlight starts to warm up."); MECHEVENT(mech, EVENT_SLITECHANGING, MechSliteChangeEvent, 5, 1); } } void mech_ams(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); SILLY_TOGGLE_MACRO(IS_ANTI_MISSILE_TECH | CL_ANTI_MISSILE_TECH, AMS_ENABLED, "Anti-Missile System turned ON", "Anti-Missile System turned OFF", "This mech is not equipped with AMS"); } void mech_fliparms(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); DOCHECK(Fallen(mech), "You're using your arms to support yourself. Try flipping something else."); SILLY_TOGGLE_MACRO(FLIPABLE_ARMS, FLIPPED_ARMS, "Arms have been flipped to BACKWARD position", "Arms have been flipped to FORWARD position", "You cannot flip the arms in this mech"); } /* Parameters: <player,mech,buffer> = parent's input nspecisspec, nspec 5 = check that it's a TAMMO weapon and has the specified spec 4 = check that weapon's SRM (or SSRM) 3 = check that weapon's NARC beacon 2 = check that weapon's LRM 1 = compare nspec to weapon's special 0 = compare nspec to weapon's type and ensure it isn't NARCbcn -1 = compare nspec to weapon's type & check for Artemis mode = mode to set if nspec check is successful onmsg = msg for turning mode on offmsg = msg for turning mode off cant = system lacks nspec */ static int temp_nspecisspec, temp_nspec, temp_mode, temp_firemode; static char *temp_onmsg, *temp_offmsg, *temp_cant; static int mech_toggle_mode_sub_func(MECH * mech, dbref player, int index, int high) { int section, critical, weaptype; weaptype = FindWeaponNumberOnMech_Advanced(mech, index, §ion, &critical, 0); DOCHECK0(weaptype == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK0(weaptype == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK0(weaptype == -3, "The weapon system chirps: 'That weapon is still reloading!'"); DOCHECK0(weaptype == -4, "The weapon system chirps: 'That weapon is still recharging!'"); DOCHECK0(GetPartFireMode(mech, section, critical) & OS_MODE, "One-shot weapons' mode cannot be altered!"); DOCHECK0(isWeapAmmoFeedLocked(mech, section, critical), "That weapon's ammo feed mechanism is damaged!"); if (temp_nspec == -1) DOCHECK0(!FindArtemisForWeapon(mech, section, critical), "You have no Artemis system for that weapon."); weaptype = Weapon2I(GetPartType(mech, section, critical)); DOCHECK0(MechWeapons[weaptype].special & ROCKET, "Rocket launchers' mode cannot be altered!"); if ((temp_nspecisspec == 5 && (MechWeapons[weaptype].type == TAMMO) && !(MechWeapons[weaptype].special & temp_nspec)) || (temp_nspecisspec == 4 && (MechWeapons[weaptype].type == TMISSILE) && !(MechWeapons[weaptype].type & (IDF | DAR))) || (temp_nspecisspec == 2 && (MechWeapons[weaptype].special & IDF) && !(MechWeapons[weaptype].special & DAR)) || (temp_nspecisspec == 1 && temp_nspec && (MechWeapons[weaptype].special & temp_nspec)) || (temp_nspecisspec <= 0 && temp_nspec && (MechWeapons[weaptype].type == temp_nspec && !(MechWeapons[weaptype].special & NARC)))) { if (temp_nspecisspec == 0 && (temp_nspec & TARTILLERY)) DOCHECK0((GetPartAmmoMode(mech, section, critical) & ARTILLERY_MODES) && !(GetPartAmmoMode(mech, section, critical) & temp_mode), "That weapon has already been set to fire special rounds!"); if (temp_firemode) { if (GetPartFireMode(mech, section, critical) & temp_mode) { GetPartFireMode(mech, section, critical) &= ~temp_mode; mech_notify(mech, MECHALL, tprintf(temp_offmsg, index)); return 0; } } else { if (GetPartAmmoMode(mech, section, critical) & temp_mode) { GetPartAmmoMode(mech, section, critical) &= ~temp_mode; mech_notify(mech, MECHALL, tprintf(temp_offmsg, index)); return 0; } } if (temp_firemode) { GetPartFireMode(mech, section, critical) &= ~FIRE_MODES; GetPartFireMode(mech, section, critical) |= temp_mode; } else { GetPartAmmoMode(mech, section, critical) &= ~AMMO_MODES; GetPartAmmoMode(mech, section, critical) |= temp_mode; } mech_notify(mech, MECHALL, tprintf(temp_onmsg, index)); return 0; } notify(player, temp_cant); return 0; } static void mech_toggle_mode_sub(dbref player, MECH * mech, char *buffer, int nspecisspec, int nspec, int mode, int tFireMode, char *onmsg, char *offmsg, char *cant) { char *args[1]; DOCHECK(mech_parseattributes(buffer, args, 1) != 1, "Please specify a weapon number."); temp_nspecisspec = nspecisspec; temp_nspec = nspec; temp_mode = mode; temp_onmsg = onmsg; temp_offmsg = offmsg; temp_cant = cant; temp_firemode = tFireMode; multi_weap_sel(mech, player, args[0], 1, mech_toggle_mode_sub_func); } void mech_flamerheat(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, CHEAT, HEAT_MODE, 1, "Weapon %d has been set to HEAT mode", "Weapon %d has been set to normal mode", "That weapon cannot be set HEAT!"); } void mech_ultra(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, ULTRA, ULTRA_MODE, 1, "Weapon %d has been set to ultra fire mode", "Weapon %d has been set to normal fire mode", "That weapon cannot be set ULTRA!"); } void mech_inarc_ammo_toggle(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; int wSection, wCritSlot, wWeapType; int wWeapNum = 0; int wcArgs = 0; char *args[2]; char strMode[30]; cch(MECH_USUALO); wcArgs = mech_parseattributes(buffer, args, 2); DOCHECK(wcArgs < 1, "Please specify a weapon number."); DOCHECK(Readnum(wWeapNum, args[0]), tprintf("Invalid value: %s", args[0])); wWeapType = FindWeaponNumberOnMech(mech, wWeapNum, &wSection, &wCritSlot); DOCHECK(wWeapType == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK(wWeapType == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK(wWeapType == -3, "The weapon system chirps: 'That weapon is still reloading!'"); DOCHECK(wWeapType == -4, "The weapon system chirps: 'That weapon is still recharging!'"); DOCHECK(!(MechWeapons[wWeapType].special & INARC), "The weapon system chirps: 'That weapon is not an iNARC launcher!'"); DOCHECK(isWeapAmmoFeedLocked(mech, wSection, wCritSlot), "That weapon's ammo feed mechanism is damaged!"); /* Change our modes... */ GetPartAmmoMode(mech, wSection, wCritSlot) &= ~AMMO_MODES; if (wcArgs < 2) strcpy(strMode, "Homing"); else { switch (toupper(args[1][0])) { case 'X': strcpy(strMode, "Explosive"); GetPartAmmoMode(mech, wSection, wCritSlot) |= INARC_EXPLO_MODE; break; case 'Y': strcpy(strMode, "Haywire"); GetPartAmmoMode(mech, wSection, wCritSlot) |= INARC_HAYWIRE_MODE; break; case 'E': strcpy(strMode, "ECM"); GetPartAmmoMode(mech, wSection, wCritSlot) |= INARC_ECM_MODE; break; case 'Z': strcpy(strMode, "Nemesis"); GetPartAmmoMode(mech, wSection, wCritSlot) |= INARC_NEMESIS_MODE; break; default: strcpy(strMode, "Homing"); break; } } mech_notify(mech, MECHALL, tprintf("Weapon %d set to fire iNARC %s pods.", wWeapNum, strMode)); } void mech_explosive(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, NARC, NARC_MODE, 0, "Weapon %d has been set to fire explosive rounds", "Weapon %d has been set to fire NARC beacons", "That weapon cannot be set to fire explosive rounds!"); } void mech_lbx(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, LBX, LBX_MODE, 0, "Weapon %d has been set to LBX fire mode", "Weapon %d has been set to normal fire mode", "That weapon cannot be set LBX!"); } void mech_armorpiercing(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, RFAC, AC_AP_MODE, 0, "Weapon %d has been set to fire AP rounds", "Weapon %d has been set to fire normal rounds", "That weapon cannot fire AP rounds!"); } void mech_flechette(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, RFAC, AC_FLECHETTE_MODE, 0, "Weapon %d has been set to fire Flechette rounds", "Weapon %d has been set to fire normal rounds", "That weapon cannot fire Flechette rounds!"); } void mech_incendiary(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, RFAC, AC_INCENDIARY_MODE, 0, "Weapon %d has been set to fire Incendiary rounds", "Weapon %d has been set to fire normal rounds", "That weapon cannot fire Incendiary rounds!"); } void mech_precision(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, RFAC, AC_PRECISION_MODE, 0, "Weapon %d has been set to fire Precision rounds", "Weapon %d has been set to fire normal rounds", "That weapon cannot fire Precision rounds!"); } void mech_rapidfire(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, RFAC, RFAC_MODE, 1, "Weapon %d has been set to Rapid Fire mode", "Weapon %d has been set to normal fire mode", "That weapon cannot be set to do rapid fire!"); } void mech_stinger(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 2, 0, STINGER_MODE, 0, "Weapon %d has been set to fire stinger missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set STINGER!"); } void mech_rac(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; int wSection, wCritSlot, wWeapType; int wWeapNum = 0; int wcArgs = 0; char *args[2]; char strMode[30]; cch(MECH_USUALO); wcArgs = mech_parseattributes(buffer, args, 2); DOCHECK(wcArgs < 1, "Please specify a weapon number."); DOCHECK(Readnum(wWeapNum, args[0]), tprintf("Invalid value: %s", args[0])); wWeapType = FindWeaponNumberOnMech(mech, wWeapNum, &wSection, &wCritSlot); DOCHECK(wWeapType == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK(wWeapType == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK(wWeapType == -3, "The weapon system chirps: 'That weapon is still reloading!'"); DOCHECK(wWeapType == -4, "The weapon system chirps: 'That weapon is still recharging!'"); DOCHECK(!(MechWeapons[wWeapType].special & RAC), "The weapon system chirps: 'That weapon is not an Rotary AC!'"); /* Change our modes... */ GetPartFireMode(mech, wSection, wCritSlot) &= ~FIRE_MODES; GetPartFireMode(mech, wSection, wCritSlot) &= ~(RAC_TWOSHOT_MODE | RAC_FOURSHOT_MODE | RAC_SIXSHOT_MODE); if (wcArgs < 2) strcpy(strMode, "one shot"); else { switch (args[1][0]) { case '2': strcpy(strMode, "two shots"); GetPartFireMode(mech, wSection, wCritSlot) |= RAC_TWOSHOT_MODE; break; case '4': strcpy(strMode, "four shots"); GetPartFireMode(mech, wSection, wCritSlot) |= RAC_FOURSHOT_MODE; break; case '6': strcpy(strMode, "six shots"); GetPartFireMode(mech, wSection, wCritSlot) |= RAC_SIXSHOT_MODE; break; default: strcpy(strMode, "one shot"); break; } } mech_notify(mech, MECHALL, tprintf("Weapon %d set to fire %s at a time.", wWeapNum, strMode)); } static int mech_unjamammo_func(MECH * mech, dbref player, int index, int high) { int section, critical, weaptype; int i; char location[50]; weaptype = FindWeaponNumberOnMech(mech, index, §ion, &critical); DOCHECK0(weaptype == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK0(weaptype == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK0(PartTempNuke(mech, section, critical) != FAIL_AMMOJAMMED, "The ammo feed mechanism for that weapon is not jammed."); DOCHECK0(Jumping(mech), "You can't unjam the ammo feed while jumping!"); DOCHECK0(IsRunning(MechDesiredSpeed(mech), MMaxSpeed(mech)), "You can't unjam the ammo feed while running!"); for (i = 0; i < NUM_SECTIONS; i++) { if (SectHasBusyWeap(mech, i)) { ArmorStringFromIndex(i, location, MechType(mech), MechMove(mech)); mech_notify(mech, MECHALL, tprintf("You have weapons recycling on your %s.", location)); return 0; } } DOCHECK0(UnJammingAmmo(mech), "You are already unjamming a weapon!"); MECHEVENT(mech, EVENT_UNJAM_AMMO, mech_unjam_ammo_event, 60, index); mech_notify(mech, MECHALL, tprintf("You begin to shake the jammed ammo loose on weapon #%d", index)); return 0; } void mech_unjamammo(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; char *args[1]; cch(MECH_USUALMO); DOCHECK(mech_parseattributes(buffer, args, 1) != 1, "Please specify a weapon number."); multi_weap_sel(mech, player, args[0], 1, mech_unjamammo_func); } void mech_gattling(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 1, GMG, GATTLING_MODE, 1, "Weapon %d has been set to Gattling mode", "Weapon %d has been set to normal fire mode", "That weapon cannot be set to do gattling fire!"); } void mech_artemis(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, -1, TMISSILE, ARTEMIS_MODE, 0, "Weapon %d has been set to fire Artemis IV compatible missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set ARTEMIS!"); } void mech_narc(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 0, TMISSILE, NARC_MODE, 0, "Weapon %d has been set to fire Narc Beacon compatible missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set NARC!"); } void mech_swarm(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 2, 0, SWARM_MODE, 0, "Weapon %d has been set to fire Swarm missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set to fire Swarm missiles!"); } void mech_swarm1(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 2, 0, SWARM1_MODE, 0, "Weapon %d has been set to fire Swarm1 missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set to fire Swarm1 missiles!"); } void mech_inferno(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 4, 0, INFERNO_MODE, 0, "Weapon %d has been set to fire Inferno missiles.", "Weapon %d has been set to fire normal missiles", "That weapon cannot be set to fire Inferno missiles!"); } void mech_hotload(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; int wSection, wCritSlot, wWeapType; int wWeapNum = 0; int wcArgs = 0; char *args[1]; cch(MECH_USUALO); wcArgs = mech_parseattributes(buffer, args, 1); DOCHECK(wcArgs < 1, "Please specify a weapon number."); DOCHECK(Readnum(wWeapNum, args[0]), tprintf("Invalid value: %s", args[0])); wWeapType = FindWeaponNumberOnMech(mech, wWeapNum, &wSection, &wCritSlot); DOCHECK(wWeapType == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK(wWeapType == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK(wWeapType == -3, "The weapon system chirps: 'That weapon is still reloading!'"); DOCHECK(wWeapType == -4, "The weapon system chirps: 'That weapon is still recharging!'"); DOCHECK(!(MechWeapons[wWeapType].special & IDF), "The weapon system chirps: 'That weapon can not be hotloaded!'"); if (GetPartFireMode(mech, wSection, wCritSlot) & HOTLOAD_MODE) { mech_notify(mech, MECHALL, tprintf("Hotloading for weapon %d has been toggled off.", wWeapNum)); GetPartFireMode(mech, wSection, wCritSlot) &= ~HOTLOAD_MODE; } else { mech_notify(mech, MECHALL, tprintf("Hotloading for weapon %d has been toggled on.", wWeapNum)); GetPartFireMode(mech, wSection, wCritSlot) |= HOTLOAD_MODE; } } void mech_cluster(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 0, TARTILLERY, CLUSTER_MODE, 0, "Weapon %d has been set to fire cluster rounds.", "Weapon %d has been set to fire normal rounds", "Invalid weapon type!"); } void mech_smoke(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 0, TARTILLERY, SMOKE_MODE, 0, "Weapon %d has been set to fire smoke rounds.", "Weapon %d has been set to fire normal rounds", "Invalid weapon type!"); } void mech_mine(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); mech_toggle_mode_sub(player, mech, buffer, 0, TARTILLERY, MINE_MODE, 0, "Weapon %d has been set to fire mine rounds.", "Weapon %d has been set to fire normal rounds", "Invalid weapon type!"); } static void mech_mascr_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; if (MechMASCCounter(mech) > 0) { MechMASCCounter(mech)--; MECHEVENT(mech, EVENT_MASC_REGEN, mech_mascr_event, MASC_TICK, 0); } } static void mech_masc_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; #ifndef BT_MOVEMENT_MODES int needed = 2 * (1 + (MechMASCCounter(mech)++)); #else int needed = (2 * (1 + (MechMASCCounter(mech)++))) + ((MechStatus2(mech) & SCHARGE_ENABLED) ? 1 : 0) + (MechStatus2(mech) & SPRINTING ? 2 : 0); #endif int roll = Roll(); if (!Started(mech)) return; if (!(MechSpecials(mech) & MASC_TECH)) return; if (MechStatus(mech) & SCHARGE_ENABLED) roll--; if (needed < 10 && Good_obj(MechPilot(mech)) && WizP(MechPilot(mech))) roll = Number(needed + 1, 12); mech_notify(mech, MECHALL, tprintf("MASC: BTH %d+, Roll: %d", needed + 1, roll)); if (roll > needed) { MECHEVENT(mech, EVENT_MASC_FAIL, mech_masc_event, MASC_TICK, 0); return; } MechSpecials(mech) &= ~MASC_TECH; MechStatus(mech) &= ~MASC_ENABLED; if (fabs(MechSpeed(mech)) > MP1) { mech_notify(mech, MECHALL, "Your leg actuators freeze suddenly, and you fall!"); MechLOSBroadcast(mech, "stops and falls in mid-step!"); MechFalls(mech, 1, 0); } else { mech_notify(mech, MECHALL, "Your leg actuators freeze suddenly!"); if (MechSpeed(mech) > 0.0) MechLOSBroadcast(mech, "stops suddenly!"); } /* Break the Hips - FASA canon rule about MASC */ DestroyPart(mech, RLEG, 0); DestroyPart(mech, LLEG, 0); if (MechMove(mech) == MOVE_QUAD) { DestroyPart(mech, RARM, 0); DestroyPart(mech, LARM, 0); } /* Let the MUX know both hips gone */ MechCritStatus(mech) |= HIP_DESTROYED; /* Reset the Speeds, this sets all 3 of them */ SetMaxSpeed(mech, 0.0); } void mech_masc(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); DOCHECK(!(MechSpecials(mech) & MASC_TECH), "Your toy ain't prepared for what you're askin' it!"); DOCHECK(MMaxSpeed(mech) < MP1, "Uh huh."); if (MechStatus(mech) & MASC_ENABLED) { mech_notify(mech, MECHALL, "MASC has been turned off."); MechStatus(mech) &= ~MASC_ENABLED; MechDesiredSpeed(mech) = MechDesiredSpeed(mech) * 3. / 4.; StopMasc(mech); MECHEVENT(mech, EVENT_MASC_REGEN, mech_mascr_event, MASC_TICK, 0); return; } mech_notify(mech, MECHALL, "MASC has been turned on."); MechStatus(mech) |= MASC_ENABLED; StopMascR(mech); MechDesiredSpeed(mech) = MechDesiredSpeed(mech) * 4. / 3.; MECHEVENT(mech, EVENT_MASC_FAIL, mech_masc_event, 1, 0); } static void mech_scharger_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; if (MechSChargeCounter(mech) > 0) { MechSChargeCounter(mech)--; MECHEVENT(mech, EVENT_SCHARGE_REGEN, mech_scharger_event, SCHARGE_TICK, 0); } } static void mech_scharge_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; #ifndef BT_MOVEMENT_MODES int needed = 2 * (1 + (MechSChargeCounter(mech)++)); #else int needed = (2 * (1 + (MechMASCCounter(mech)++))) + ((MechStatus(mech) & MASC_ENABLED) ? 1 : 0) + (MechStatus2(mech) & SPRINTING ? 2 : 0); #endif int roll = Roll(); int j, count = 0; int maxspeed, newmaxspeed = 0; int critType; char msgbuf[MBUF_SIZE]; if (!Started(mech)) return; if (!(MechSpecials2(mech) & SUPERCHARGER_TECH)) return; if (MechStatus(mech) & MASC_ENABLED) roll = roll - 1; if (needed < 10 && Good_obj(MechPilot(mech)) && WizP(MechPilot(mech))) roll = Number(needed + 1, 12); mech_notify(mech, MECHALL, tprintf("Supercharger: BTH %d, Roll: %d", needed + 1, roll)); if (roll > needed) { MECHEVENT(mech, EVENT_SCHARGE_FAIL, mech_scharge_event, SCHARGE_TICK, 0); return; } MechSpecials2(mech) &= ~SUPERCHARGER_TECH; MechStatus(mech) &= ~SCHARGE_ENABLED; mech_notify(mech, MECHALL, "Your supercharger overloads and explodes!"); if (MechType(mech) == CLASS_MECH) { for (j = 0; j < CritsInLoc(mech, CTORSO); j++) { critType = GetPartType(mech, CTORSO, j); if (critType == Special(SUPERCHARGER)) { if (!PartIsDestroyed(mech, CTORSO, j)) DestroyPart(mech, CTORSO, j); } } count = Number(1, 4); for (j = 0; count && j < CritsInLoc(mech, CTORSO); j++) { critType = GetPartType(mech, CTORSO, j); if (critType == Special(ENGINE) && !PartIsDestroyed(mech, CTORSO, j)) { DestroyPart(mech, CTORSO, j); if (!Destroyed(mech) && Started(mech)) { sprintf(msgbuf, "'s center torso spews black smoke!"); MechLOSBroadcast(mech, msgbuf); } if (MechEngineHeat(mech) < 10) { MechEngineHeat(mech) += 5; mech_notify(mech, MECHALL, "Your engine shielding takes a hit! It's getting hotter in here!!"); } else if (MechEngineHeat(mech) < 15) { MechEngineHeat(mech) = 15; mech_notify(mech, MECHALL, "Your engine is destroyed!!"); DestroyMech(mech, mech, 1); } count--; } } } if ((MechType(mech) == CLASS_VTOL) || (MechType(mech) == CLASS_VEH_GROUND)) { sprintf(msgbuf, " coughs think black smoke from its exhaust."); MechLOSBroadcast(mech, msgbuf); maxspeed = MechMaxSpeed(mech); newmaxspeed = (maxspeed * .5); SetMaxSpeed(mech, newmaxspeed); } } void mech_scharge(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALMO); DOCHECK(!(MechSpecials2(mech) & SUPERCHARGER_TECH), "Your toy ain't prepared for what you're askin' it!"); DOCHECK(MMaxSpeed(mech) < MP1, "Uh huh."); if (MechStatus(mech) & SCHARGE_ENABLED) { mech_notify(mech, MECHALL, "Supercharger has been turned off."); MechStatus(mech) &= ~SCHARGE_ENABLED; MechDesiredSpeed(mech) = MechDesiredSpeed(mech) * 3. / 4.; StopSCharge(mech); MECHEVENT(mech, EVENT_SCHARGE_REGEN, mech_scharger_event, SCHARGE_TICK, 0); return; } mech_notify(mech, MECHALL, "Supercharger has been turned on."); MechStatus(mech) |= SCHARGE_ENABLED; StopSChargeR(mech); MechDesiredSpeed(mech) = MechDesiredSpeed(mech) * 4. / 3.; MECHEVENT(mech, EVENT_SCHARGE_FAIL, mech_scharge_event, 1, 0); } int doing_explode = 0; static void mech_explode_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; MAP *map; int extra = (int) e->data2; int i, j, damage; int z; int dam; if (Destroyed(mech) || !Started(mech)) return; if (extra > 256 && !FindDestructiveAmmo(mech, &i, &j)) return; if ((--extra) % 256) { mech_notify(mech, MECHALL, tprintf("Self-destruction in %d second%s..", extra % 256, extra > 1 ? "s" : "")); MECHEVENT(mech, EVENT_EXPLODE, mech_explode_event, 1, extra); } else { SendDebug(tprintf("#%d explodes.", mech->mynum)); if (extra >= 256) { SendDebug(tprintf("#%d explodes [ammo]", mech->mynum)); mech_notify(mech, MECHALL, "All your ammo explodes!"); while ((damage = FindDestructiveAmmo(mech, &i, &j))) ammo_explosion(mech, mech, i, j, damage); } else { SendDebug(tprintf("#%d explodes [reactor]", mech->mynum)); MechLOSBroadcast(mech, "suddenly explodes!"); doing_explode = 1; mech_notify(mech, MECHALL, "Suddenly you feel great heat overcoming your senses.. you faint.. (and die)"); z = MechZ(mech); DestroySection(mech, mech, -1, LTORSO); DestroySection(mech, mech, -1, RTORSO); DestroySection(mech, mech, -1, CTORSO); DestroySection(mech, mech, -1, HEAD); MechZ(mech) += 6; doing_explode = 0; if (mudconf.btech_explode_reactor > 1) dam = MAX(MechTons(mech) / 5, MechEngineSize(mech) / 15); else dam = MAX(MechTons(mech) / 5, MechEngineSize(mech) / 10); /* If the guy is on a map have it hit the hexes around it */ map = FindObjectsData(mech->mapindex); if (map) { blast_hit_hexesf(map, dam, 1, MAX(MechTons(mech) / 10, MechEngineSize(mech) / 25), MechFX(mech), MechFY(mech), MechFX(mech), MechFY(mech), "%ch%crYou bear full brunt of the blast!%cn", "is hit badly by the blast!", "%ch%cyYou receive some damage from the blast!%cn", "is hit by the blast!", mudconf.btech_explode_reactor > 1, mudconf.btech_explode_reactor > 1 ? 5 : 3, 5, 1, 2); } MechZ(mech) = z; headhitmwdamage(mech, 4); } } } void mech_explode(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; char *args[3]; int i; int ammoloc, ammocritnum; int time = mudconf.btech_explode_time; int ammo = 1; int argc; cch(MECH_USUALO); argc = mech_parseattributes(buffer, args, 2); DOCHECK(argc != 1, "Invalid number of arguments!"); /* Can't do any of the explosion routine if we're recycling! */ for (i = 0; i < NUM_SECTIONS; i++) { if (!SectIsDestroyed(mech, i)) DOCHECK(SectHasBusyWeap(mech, i), "You have weapons recycling!"); DOCHECK(MechSections(mech)[i].recycle, "You are still recovering from your last attack."); } if (!strcasecmp(buffer, "stop")) { DOCHECK(!mudconf.btech_explode_stop, "It's too late to turn back now!"); DOCHECK(!Exploding(mech), "Your mech isn't undergoing a self-destruct sequence!"); StopExploding(mech); mech_notify(mech, MECHALL, "Self-destruction sequence aborted."); SendDebug(tprintf ("#%d in #%d stopped the self-destruction sequence.", player, mech->mynum)); MechLOSBroadcast(mech, "regains control over itself."); return; } DOCHECK(Exploding(mech), "Your mech is already undergoing a self-destruct sequence!"); if (!strcasecmp(buffer, "ammo")) { /* Find SOME ammo to explode ; if possible, we engage the 'boom' process */ DOCHECK(!mudconf.btech_explode_ammo, "You can't bring yourself to do it!"); i = FindDestructiveAmmo(mech, &ammoloc, &ammocritnum); DOCHECK(!i, "There is no 'damaging' ammo on your 'mech!"); /* Engage the boom-event */ SendDebug(tprintf ("#%d in #%d initiates the ammo explosion sequence.", player, mech->mynum)); MechLOSBroadcast(mech, "starts billowing smoke!"); time = time / 2; MECHEVENT(mech, EVENT_EXPLODE, mech_explode_event, 1, time); } else { DOCHECK(!mudconf.btech_explode_reactor, "You can't bring yourself to do it!"); DOCHECK(MechType(mech) != CLASS_MECH, "Only mechs can do the 'big boom' effect."); DOCHECK(MechSpecials(mech) & ICE_TECH, "You need a fusion reactor."); SendDebug(tprintf ("#%d in #%d initiates the reactor explosion sequence.", player, mech->mynum)); MechLOSBroadcast(mech, "loses reactions containment!"); MECHEVENT(mech, EVENT_EXPLODE, mech_explode_event, 1, time); ammo = 0; } mech_notify(mech, MECHALL, "Self-destruction sequence engaged ; please stand by."); mech_notify(mech, MECHALL, tprintf("%s in %d seconds.", ammo ? "The ammunition will explode" : "The reactor will blow up", time)); /* Null out the pilot to disallow further commands */ MechPilot(mech) = -1; } static void mech_dig_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; if (!Digging(mech)) return; if (!Started(mech)) return; MechTankCritStatus(mech) &= ~DIGGING_IN; MechTankCritStatus(mech) |= DUG_IN; mech_notify(mech, MECHALL, "You finish burrowing for cover - only turret weapons are available now."); } void mech_dig(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALO); DOCHECK(fabs(MechSpeed(mech)) > 0.0, "You are moving!"); DOCHECK(MechFacing(mech) != MechDesiredFacing(mech), "You are turning!"); DOCHECK(MechMove(mech) == MOVE_NONE, "You are stationary!"); DOCHECK(MechDugIn(mech), "You are already dug in!"); DOCHECK(Digging(mech), "You are already digging in!"); DOCHECK(OODing(mech), "While dropping? I think not."); DOCHECK(MechRTerrain(mech) == ROAD || MechRTerrain(mech) == BRIDGE || MechRTerrain(mech) == BUILDING || MechRTerrain(mech) == WALL, "The surface is slightly too hard for you to dig in."); DOCHECK(MechRTerrain(mech) == WATER, "In water? Who are you kidding?"); MechTankCritStatus(mech) |= DIGGING_IN; MECHEVENT(mech, EVENT_DIG, mech_dig_event, 20, 0); mech_notify(mech, MECHALL, "You start digging yourself in a nice hole.."); } static void mech_unjam_turret_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data; if (Destroyed(mech)) return; if (Uncon(mech)) return; if (!GetSectInt(mech, TURRET)) return; if (!Started(mech)) return; if (MechTankCritStatus(mech) & TURRET_LOCKED) { mech_notify(mech, MECHALL, "You are unable to unjam the turret!"); return; } MechTankCritStatus(mech) &= ~TURRET_JAMMED; mech_notify(mech, MECHALL, "You manage to unjam your turret!"); } void mech_fixturret(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; cch(MECH_USUALO); DOCHECK(MechTankCritStatus(mech) & TURRET_LOCKED, "Your turret is locked! You need a repairbay to fix it!"); DOCHECK(!(MechTankCritStatus(mech) & TURRET_JAMMED), "Your turret is not jammed!"); MECHEVENT(mech, EVENT_UNJAM_TURRET, mech_unjam_turret_event, 60, 0); mech_notify(mech, MECHALL, "You start to repair your jammed turret."); } static int mech_disableweap_func(MECH * mech, dbref player, int index, int high) { int section, critical, weaptype; weaptype = FindWeaponNumberOnMech_Advanced(mech, index, §ion, &critical, 1); DOCHECK0(weaptype == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK0(weaptype == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); weaptype = Weapon2I(GetPartType(mech, section, critical)); DOCHECK0(!(MechWeapons[weaptype].special & GAUSS), "You can only disable Gauss weapons."); SetPartTempNuke(mech, section, critical, FAIL_DESTROYED); mech_notify(mech, MECHALL, tprintf("You power down weapon %d.", index)); return 0; } void mech_disableweap(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; char *args[1]; cch(MECH_USUALO); DOCHECK(mech_parseattributes(buffer, args, 1) != 1, "Please specify a weapon number."); multi_weap_sel(mech, player, args[0], 1, mech_disableweap_func); } int FindMainWeapon(MECH * mech, int (*callback) (MECH *, int, int, int, int)) { unsigned char weaparray[MAX_WEAPS_SECTION]; unsigned char weapdata[MAX_WEAPS_SECTION]; int critical[MAX_WEAPS_SECTION]; int count; int loop; int ii; int tempcrit; int maxcrit = 0; int maxloc = 0; int critfound = 0; int maxcount = 0; for (loop = 0; loop < NUM_SECTIONS; loop++) { if (SectIsDestroyed(mech, loop)) continue; count = FindWeapons(mech, loop, weaparray, weapdata, critical); if (count > 0) { for (ii = 0; ii < count; ii++) { if (!PartIsBroken(mech, loop, critical[ii])) { /* tempcrit = GetWeaponCrits(mech, weaparray[ii]); */ tempcrit = rand(); if (tempcrit > maxcrit) { critfound = 1; maxcrit = tempcrit; maxloc = loop; maxcount = ii; } } } } } if (critfound) return callback(mech, maxloc, weaparray[maxcount], maxcount, maxcrit); else return 0; } void changeStealthArmorEvent(MUXEVENT * e) { MECH *mech = (MECH *) e->data; int wType = (int) e->data2; if (!Started(mech)) return; if (!HasWorkingECMSuite(mech)) return; if (wType) { mech_notify(mech, MECHALL, "Stealth Armor system engaged!"); EnableStealthArmor(mech); checkECM(mech); MarkForLOSUpdate(mech); } else { mech_notify(mech, MECHALL, "Stealth Armor system disengaged!"); DisableStealthArmor(mech); checkECM(mech); MarkForLOSUpdate(mech); } } void mech_stealtharmor(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); if (!(MechSpecials2(mech) & STEALTH_ARMOR_TECH)) { mech_notify(mech, MECHALL, "Your 'mech isn't equipped with a Stealth Armor system!"); return; } if (!HasWorkingECMSuite(mech)) { mech_notify(mech, MECHALL, "Your 'mech doesn't have a working Guardian ECM suite!"); return; } if (StealthArmorChanging(mech)) { mech_notify(mech, MECHALL, "You are already changing the status of your Stealth Armor system!"); return; } if (!StealthArmorActive(mech)) { mech_notify(mech, MECHALL, "Your Stealth Armor system begins to come online."); MECHEVENT(mech, EVENT_STEALTH_ARMOR, changeStealthArmorEvent, 30, 1); } else { mech_notify(mech, MECHALL, "Your Stealth Armor system begins to shutdown."); MECHEVENT(mech, EVENT_STEALTH_ARMOR, changeStealthArmorEvent, 30, 0); } } void changeNullSigSysEvent(MUXEVENT * e) { MECH *mech = (MECH *) e->data; int wType = (int) e->data2; if (!Started(mech)) return; if (NullSigSysDest(mech)) return; if (wType) { mech_notify(mech, MECHALL, "Null Signature System engaged!"); EnableNullSigSys(mech); MarkForLOSUpdate(mech); } else { mech_notify(mech, MECHALL, "Null Signature System disengaged!"); DisableNullSigSys(mech); MarkForLOSUpdate(mech); } } void mech_nullsig(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALO); if (!(MechSpecials2(mech) & NULLSIGSYS_TECH)) { mech_notify(mech, MECHALL, "Your 'mech isn't equipped with a Null Signature System!"); return; } if (NullSigSysDest(mech)) { mech_notify(mech, MECHALL, "Your Null Signature System is destroyed!"); return; } if (NullSigSysChanging(mech)) { mech_notify(mech, MECHALL, "You are already changing the status of your Null Signature System!"); return; } if (!NullSigSysActive(mech)) { mech_notify(mech, MECHALL, "Your Null Signature System begins to come online."); MECHEVENT(mech, EVENT_NSS, changeNullSigSysEvent, 30, 1); } else { mech_notify(mech, MECHALL, "Your Null Signature System begins to shutdown."); MECHEVENT(mech, EVENT_NSS, changeNullSigSysEvent, 30, 0); } } void show_narc_pods(dbref player, MECH * mech, char *buffer) { char location[50]; int i; cch(MECH_USUALO); if (!(checkAllSections(mech, NARC_ATTACHED) || checkAllSections(mech, INARC_HOMING_ATTACHED) || checkAllSections(mech, INARC_HAYWIRE_ATTACHED) || checkAllSections(mech, INARC_ECM_ATTACHED) || checkAllSections(mech, INARC_NEMESIS_ATTACHED))) { notify(player, "There are no NARC or iNARC pods attached to this unit."); return; } notify(player, "=========================Attached NARC and iNARC Pods========================"); notify(player, "-- Location ---||- NARC -||- iHoming -||- iHaywire -||- iECM -||- iNemesis --"); for (i = 0; i < NUM_SECTIONS; i++) { if (GetSectOInt(mech, i) > 0) { ArmorStringFromIndex(i, location, MechType(mech), MechMove(mech)); if (SectIsDestroyed(mech, i)) { notify(player, tprintf (" %-14.13s||********||***********||************||********||************* ", location)); } else { notify(player, tprintf (" %-14.13s||....%s...||.....%s.....||......%s.....||....%s...||......%s...... ", location, checkSectionForSpecial(mech, NARC_ATTACHED, i) ? "X" : ".", checkSectionForSpecial(mech, INARC_HOMING_ATTACHED, i) ? "X" : ".", checkSectionForSpecial(mech, INARC_HAYWIRE_ATTACHED, i) ? "X" : ".", checkSectionForSpecial(mech, INARC_ECM_ATTACHED, i) ? "X" : ".", checkSectionForSpecial(mech, INARC_NEMESIS_ATTACHED, i) ? "X" : ".")); } } } } int findArmBTHMod(MECH * mech, int wSec) { int wRet = 0; if (PartIsNonfunctional(mech, wSec, 1) || GetPartType(mech, wSec, 1) != I2Special(UPPER_ACTUATOR)) wRet += 2; if (PartIsNonfunctional(mech, wSec, 2) || GetPartType(mech, wSec, 2) != I2Special(LOWER_ACTUATOR)) wRet += 2; if (PartIsNonfunctional(mech, wSec, 3) || GetPartType(mech, wSec, 3) != I2Special(HAND_OR_FOOT_ACTUATOR)) wRet += 1; return wRet; } void remove_inarc_pods_mech(dbref player, MECH * mech, char *buffer) { int wLoc; int wArmToUse = -1; char *args[2]; char strLocation[50], strPunchWith[50]; int wBTH = 0; int wBTHModLARM = 0; int wBTHModRARM = 0; int wRAAvail = 1; int wLAAvail = 1; int wRoll; int wSelfDamage; int wPodType = INARC_HOMING_ATTACHED; char strPodType[30]; cch(MECH_USUALO); DOCHECK(MechIsQuad(mech), "Quads can not knock of iNARC pods!"); DOCHECK(mech_parseattributes(buffer, args, 2) != 2, "Invalid number of arguments!"); wLoc = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]); DOCHECK(wLoc == -1, "Invalid section!"); DOCHECK(!GetSectOInt(mech, wLoc), "Invalid section!"); DOCHECK(!GetSectInt(mech, wLoc), "That section is destroyed!"); ArmorStringFromIndex(wLoc, strLocation, MechType(mech), MechMove(mech)); /* Figure out wot type of pods we want to remove */ switch (toupper(args[1][0])) { case 'Y': strcpy(strPodType, "Haywire"); wPodType = INARC_HAYWIRE_ATTACHED; break; case 'E': strcpy(strPodType, "ECM"); wPodType = INARC_ECM_ATTACHED; break; default: strcpy(strPodType, "Homing"); wPodType = INARC_HOMING_ATTACHED; break; } DOCHECK(!checkSectionForSpecial(mech, wPodType, wLoc), tprintf("There are no iNarc %s pods attached to your %s!", strPodType, strLocation)); DOCHECK(((!GetSectInt(mech, RARM)) && (!GetSectInt(mech, LARM))), "You need atleast one functioning arm to remove iNarc pods!"); if (wLoc == RARM) { DOCHECK(!GetSectInt(mech, LARM), "Your Left Arm needs to be intact to take iNarc pods off your right arm!"); DOCHECK(SectHasBusyWeap(mech, LARM), "You have weapons recycling on your Left Arm."); DOCHECK(MechSections(mech)[LARM].recycle, "Your Left Arm is still recovering from your last attack."); wArmToUse = LARM; } if (wLoc == LARM) { DOCHECK(!GetSectInt(mech, RARM), "Your Right Arm needs to be intact to take iNarc pods off your Left Arm!"); DOCHECK(SectHasBusyWeap(mech, RARM), "You have weapons recycling on your Right Arm."); DOCHECK(MechSections(mech)[RARM].recycle, "Your Right Arm is still recovering from your last attack."); wArmToUse = RARM; } if (wArmToUse == -1) { if (SectHasBusyWeap(mech, RARM) || MechSections(mech)[RARM].recycle || (!GetSectInt(mech, RARM))) wRAAvail = 0; if (SectHasBusyWeap(mech, LARM) || MechSections(mech)[LARM].recycle || (!GetSectInt(mech, LARM))) wLAAvail = 0; DOCHECK(!(wLAAvail || wRAAvail), "You need atleast one arm that is not recycling and does not have weapons recycling in it!"); if (!wLAAvail) wBTHModLARM = 1000; else wBTHModLARM = findArmBTHMod(mech, LARM); if (!wRAAvail) wBTHModRARM = 1000; else wBTHModRARM = findArmBTHMod(mech, RARM); if (wBTHModRARM < wBTHModLARM) { wBTH = wBTHModRARM; wArmToUse = RARM; } else { wBTH = wBTHModLARM; wArmToUse = LARM; } } else { wBTH = findArmBTHMod(mech, wArmToUse); } wBTH += FindPilotPiloting(mech) + 4; wRoll = Roll(); ArmorStringFromIndex(wArmToUse, strPunchWith, MechType(mech), MechMove(mech)); mech_notify(mech, MECHALL, tprintf ("You try to swat at the iNarc pods attached to your %s with your %s. BTH: %d,\tRoll: %d", strLocation, strPunchWith, wBTH, wRoll)); /* Oops, we failed! */ if (wRoll < wBTH) { mech_notify(mech, MECHALL, "Uh oh. You miss the pod and hit yourself!"); MechLOSBroadcast(mech, "tries to swat off an iNarc pod, but misses and hits itself!"); wSelfDamage = (MechTons(mech) + 10 / 2) / 10; if (!OkayCritSectS(wArmToUse, 2, LOWER_ACTUATOR)) wSelfDamage = wSelfDamage / 2; if (!OkayCritSectS(wArmToUse, 1, UPPER_ACTUATOR)) wSelfDamage = wSelfDamage / 2; DamageMech(mech, mech, 1, MechPilot(mech), wLoc, 0, 0, wSelfDamage, 0, -1, 0, -1, 0, 0); } else { MechSections(mech)[wLoc].specials &= ~wPodType; mech_notify(mech, MECHALL, tprintf("You knock a %s pod off your %s!", strPodType, strLocation)); MechLOSBroadcast(mech, "knocks an iNarc pod off itself."); } SetRecycleLimb(mech, wArmToUse, PHYSICAL_RECYCLE_TIME); } void removeiNarcPodsTank(MUXEVENT * e) { MECH *mech = (MECH *) e->data; int i; if (Destroyed(mech)) return; mech_notify(mech, MECHALL, "You remove all the iNARC pods from your unit."); MechLOSBroadcast(mech, "'s crew climbs out and knocks off all the attached iNarc pods!"); for (i = 0; i < NUM_SECTIONS; i++) { if (GetSectOInt(mech, i) > 0) { MechSections(mech)[i].specials &= ~(INARC_HOMING_ATTACHED | INARC_HAYWIRE_ATTACHED | INARC_ECM_ATTACHED | INARC_NEMESIS_ATTACHED); } } } void remove_inarc_pods_tank(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALSO); DOCHECK((MechDesiredSpeed(mech) > 0), "You can not be moving when attempting to remove iNarc pods!"); DOCHECK((MechSpeed(mech) > 0), "You can not be moving when attempting to remove iNarc pods!"); if (MechType(mech) == CLASS_VTOL) DOCHECK(!Landed(mech), "You must land before attempting to remove iNarc pods!"); DOCHECK(CrewStunned(mech), "You're too stunned to remove iNarc pods!"); DOCHECK(UnjammingTurret(mech), "You're too busy unjamming your turret to remove iNarc pods!"); DOCHECK(UnJammingAmmo(mech), "You're too busy unjamming a weapon to remove iNarc pods!"); if (!(checkAllSections(mech, INARC_HOMING_ATTACHED) || checkAllSections(mech, INARC_HAYWIRE_ATTACHED) || checkAllSections(mech, INARC_ECM_ATTACHED) || checkAllSections(mech, INARC_NEMESIS_ATTACHED))) { mech_notify(mech, MECHALL, "There are no iNarc pods attached to this unit."); return; } mech_notify(mech, MECHALL, "You begin to systematically remove all the iNarc pods from your unit."); MECHEVENT(mech, EVENT_REMOVE_PODS, removeiNarcPodsTank, 60, 0); } void mech_auto_turret(dbref player, MECH * mech, char *buffer) { cch(MECH_USUALSO); DOCHECK(!GetSectInt(mech, TURRET), "You have no turret to autoturn!"); mech_notify(mech, MECHALL, tprintf("Automatic turret turning is now %s", (MechStatus2(mech) & AUTOTURN_TURRET) ? "OFF" : "ON")); if (MechStatus2(mech) & AUTOTURN_TURRET) MechStatus2(mech) &= ~AUTOTURN_TURRET; else MechStatus2(mech) |= AUTOTURN_TURRET; } void mech_usebin(dbref player, MECH * mech, char *buffer) { char strLocation[80]; int wLoc, wCurLoc; int wSection, wCritSlot, wWeapNum, wWeapType; char *args[2]; cch(MECH_USUALSO); DOCHECK(mech_parseattributes(buffer, args, 2) != 2, "Invalid number of arguments!"); DOCHECK(Readnum(wWeapNum, args[0]), tprintf("Invalid value: %s", args[0])); wWeapType = FindWeaponNumberOnMech(mech, wWeapNum, &wSection, &wCritSlot); DOCHECK(wWeapType == -1, "The weapons system chirps: 'Illegal Weapon Number!'"); DOCHECK(wWeapType == -2, "The weapons system chirps: 'That Weapon has been destroyed!'"); DOCHECK(wWeapType == -3, "The weapon system chirps: 'That weapon is still reloading!'"); DOCHECK(wWeapType == -4, "The weapon system chirps: 'That weapon is still recharging!'"); DOCHECK(IsEnergy(wWeapType), "Energy weapons do not use ammo!"); if (args[1][0] == '-') { mech_notify(mech, MECHALL, tprintf("Prefered ammo source reset for weapon #%d", wWeapNum)); SetPartDesiredAmmoLoc(mech, wSection, wCritSlot, -1); return; } wLoc = ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]); DOCHECK(wLoc == -1, "Invalid section!"); DOCHECK(!GetSectOInt(mech, wLoc), "Invalid section!"); DOCHECK(!GetSectInt(mech, wLoc), "That section is destroyed!"); ArmorStringFromIndex(wLoc, strLocation, MechType(mech), MechMove(mech)); wCurLoc = GetPartDesiredAmmoLoc(mech, wSection, wCritSlot); DOCHECK(wCurLoc == wLoc, tprintf("Prefered ammo source already set to %s for weapon #%d", strLocation, wWeapNum)); mech_notify(mech, MECHALL, tprintf("Prefered ammo source set to %s for weapon #%d", strLocation, wWeapNum)); SetPartDesiredAmmoLoc(mech, wSection, wCritSlot, wLoc); } void mech_safety(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; DOCHECK(MechType(mech) == CLASS_MW, "Your weapons dont have safeties."); if (buffer && !strcasecmp(buffer, "on")) { UnSetMechPKiller(mech); mech_notify(mech, MECHALL, "Safeties flipped %ch%cgON%cn."); return; } if (buffer && !strcasecmp(buffer, "off")) { SetMechPKiller(mech); mech_notify(mech, MECHALL, "Safeties flipped %ch%crOFF%cn."); return; } mech_notify(mech, MECHPILOT, tprintf("Weapon safeties are %%ch%s%%cn", MechPKiller(mech) ? "%crOFF" : "%cgON")); return; } #define MECHPREF_FLAG_INVERTED 0x01 #define MECHPREF_FLAG_NEGATIVE 0x02 static struct mechpref_info { unsigned char bit; unsigned char flags; char * name; char * msg; } mech_preferences[] = { { MECHPREF_PKILL, MECHPREF_FLAG_INVERTED, "MWSafety", "MechWarrior Safeties flipped" }, { MECHPREF_SLWARN, 0, "SLWarn", "The warning when lit by searchlight is now" }, { MECHPREF_AUTOFALL, MECHPREF_FLAG_NEGATIVE, "AutoFall", "Suicidal jumps off cliffs toggled" }, { MECHPREF_NOARMORWARN, MECHPREF_FLAG_INVERTED, "ArmorWarn", "Low-armor warnings turned" }, { MECHPREF_NOAMMOWARN, MECHPREF_FLAG_INVERTED, "AmmoWarn", "Warning when running out of Ammunition switched" }, { MECHPREF_AUTOCON_SD, MECHPREF_FLAG_NEGATIVE, "AutoconShutdown", "Autocon on shutdown units turned" }, { MECHPREF_NOFRIENDLYFIRE, 0, "FFSafety", "Friendly Fire Safeties flipped" }, }; #define NUM_MECHPREFERENCES (sizeof(mech_preferences) / sizeof(struct mechpref_info)) static MECH *target_mech; static char *display_mechpref(int i) { static char buf[256]; struct mechpref_info info = mech_preferences[i]; char * state; if (!target_mech) { SendError("Invalid target_mech in display_mechpref!"); return "Unknown error; contact a Wizard."; } if (((MechPrefs(target_mech) & info.bit) && (info.flags & MECHPREF_FLAG_INVERTED)) || (!(MechPrefs(target_mech) & info.bit) && !(info.flags & MECHPREF_FLAG_INVERTED))) { if (info.flags & MECHPREF_FLAG_NEGATIVE) state = "%ch%cgOFF%cn"; else state = "%ch%crOFF%cn"; } else { if (info.flags & MECHPREF_FLAG_NEGATIVE) state = "%ch%crON%cn"; else state = "%ch%cgON%cn"; } sprintf(buf, " %-40s%s", info.name, state); return buf; } void mech_mechprefs(dbref player, void * data, char * buffer) { MECH * mech = (MECH *) data; int nargs; char *args[3]; char buf[LBUF_SIZE]; coolmenu *c; cch(MECH_USUALSMO); nargs = mech_parseattributes(buffer, args, 2); /* Default, no arguments passed */ if (!nargs) { /* Show mechprefs */ target_mech = mech; c = SelCol_FunStringMenuK(1, "Mech Preferences", display_mechpref, NUM_MECHPREFERENCES); ShowCoolMenu(player, c); KillCoolMenu(c); target_mech = NULL; } else { int i; struct mechpref_info info; char *newstate; /* Looking through the different mech preferences to find the * one the user wants to change */ for (i = 0; i < NUM_MECHPREFERENCES; i++) { if (strcasecmp(args[0], mech_preferences[i].name) == 0) break; } if (i == NUM_MECHPREFERENCES) { snprintf(buf, LBUF_SIZE, "Unknown MechPreference: %s", args[0]); notify(player, buf); return; } /* Get the current setting */ info = mech_preferences[i]; /* Did they provide a ON or OFF flag */ if (nargs == 2) { /* Check to make sure its either ON or OFF */ if ((strcasecmp(args[1], "ON") != 0) && (strcasecmp(args[1], "OFF") != 0)) { /* Insert notify here */ notify(player, "Only accept ON or OFF as valid extra " "parameter for mechprefs pref"); return; } /* Set the value to what they want */ if (strcasecmp(args[1], "ON") == 0) { /* Set the bit */ if (info.flags & MECHPREF_FLAG_INVERTED) { MechPrefs(mech) &= ~(info.bit); } else { MechPrefs(mech) |= (info.bit); } } else { /* Unset the bit */ if (info.flags & MECHPREF_FLAG_INVERTED) { MechPrefs(mech) |= (info.bit); } else { MechPrefs(mech) &= ~(info.bit); } } } else { /* If set, unset it, otherwise set the preference */ if (MechPrefs(mech) & info.bit) MechPrefs(mech) &= ~(info.bit); else MechPrefs(mech) |= (info.bit); } /* Which way did the preference get changed and * is it the default or non-standard mode of * the preference */ if (((MechPrefs(mech) & info.bit) && (info.flags & MECHPREF_FLAG_INVERTED)) || (!(MechPrefs(mech) & info.bit) && !(info.flags & MECHPREF_FLAG_INVERTED))) { if (info.flags & MECHPREF_FLAG_NEGATIVE) newstate = "%ch%cgOFF%cn"; else newstate = "%ch%crOFF%cn"; } else { if (info.flags & MECHPREF_FLAG_NEGATIVE) newstate = "%ch%crON%cn"; else newstate = "%ch%cgON%cn"; } /* Tell them the preference has been changed */ snprintf(buf, LBUF_SIZE, "%s %s", info.msg, newstate); notify(player, buf); } }