/* * $Id: map.conditions.c,v 1.2 2005/01/15 16:57:14 kstevens Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1997 Markus Stenberg * Copyright (c) 1998-2002 Thomas Wouters * Copyright (c) 2000-2002 Cord Awtry * All rights reserved * * Created: Wed Apr 23 15:18:01 1997 fingon * Last modified: Thu Sep 10 07:35:26 1998 fingon * */ #include "mech.h" #include "mech.events.h" #include "p.map.conditions.h" #include "p.mech.utils.h" #include "p.mech.combat.h" #include "p.mech.combat.misc.h" #include "p.mech.damage.h" #include "p.artillery.h" #include "p.btechstats.h" #include "p.eject.h" #include "p.mech.sensor.h" #include "p.crit.h" void alter_conditions(MAP * map) { int i; MECH *mech; for (i = 0; i < map->first_free; i++) if ((mech = FindObjectsData(map->mechsOnMap[i]))) { UpdateConditions(mech, map); #if 0 mech_notify(mech, MECHALL, "You notice a great disturbance in the Force.."); #endif } } void map_setconditions(dbref player, MAP * map, char *buffer) { char *args[5]; int vacuum = -1, underground = -1, grav, temp, argc; int fl; DOCHECK((argc = mech_parseattributes(buffer, args, 4)) < 2, "(At least) 2 options required (gravity + temperature)"); DOCHECK(argc > 4, "Too many options! Command accepts only 4 at max (gravity + temperature + vacuum-flag + underground-flag)"); DOCHECK(Readnum(grav, args[0]), "Invalid gravity (must be integer in range of 0 to 255)"); DOCHECK(grav < 0 || grav > 255, "Invalid gravity (must be integer in range of 0 to 255)"); DOCHECK(Readnum(temp, args[1]), "Invalid temperature (must be integer in range of -128 to 127"); DOCHECK(temp < -128 || temp > 127, "Invalid temperature (must be integer in range of -128 to 127"); if (argc > 2) { DOCHECK(Readnum(vacuum, args[2]), "Invalid vacuum flag (must be integer, 0 or 1)"); DOCHECK(vacuum < 0 || vacuum > 1, "Invalid vacuum flag (must be integer, 0 or 1)"); } if (argc > 3) { DOCHECK(Readnum(underground, args[3]), "Invalid underground flag (must be integer, 0 or 1)"); DOCHECK(underground < 0 || underground > 1, "Invalid underground flag (must be integer, 0 or 1)"); } fl = (map->flags & (~(MAPFLAG_SPEC | MAPFLAG_VACUUM))); if (vacuum > 0) fl |= MAPFLAG_VACUUM; if (underground > 0) fl |= MAPFLAG_UNDERGROUND; if (fl & MAPFLAG_VACUUM) fl |= MAPFLAG_SPEC; if (temp < -30 || temp > 50 || grav != 100) fl |= MAPFLAG_SPEC; map->temp = temp; map->grav = grav; map->flags = fl; notify(player, "Conditions set!"); alter_conditions(map); } void UpdateConditions(MECH * mech, MAP * map) { if (!mech) return; MechStatus(mech) &= ~CONDITIONS; if (!map) return; if (!MapUnderSpecialRules(map)) return; MechStatus(mech) |= UNDERSPECIAL; if (MapTemperature(map) < -30 || MapTemperature(map) > 50) MechStatus(mech) |= UNDERTEMPERATURE; if (MapGravity(map) != 100) MechStatus(mech) |= UNDERGRAVITY; if (MapIsVacuum(map)) MechStatus(mech) |= UNDERVACUUM; } extern int doing_explode; void check_stackpole(MECH * wounded, MECH * attacker) { if (mudconf.btech_stackpole && !doing_explode && (MechBoomStart(wounded) + MAX_BOOM_TIME) >= muxevent_tick && Roll() >= BOOM_BTH && (Started(wounded) || Starting(wounded))) { int z = MechZ(wounded); MAP * map = getMap(wounded->mapindex); dbref wounded_pilot = MechPilot(wounded); int dam; HexLOSBroadcast(map, MechX(wounded), MechY(wounded), "%ch%crThe hit destroys last safety systems, " "releasing the fusion reaction!%cn"); DestroySection(wounded, attacker, 0, CTORSO); DestroySection(wounded, attacker, 0, LTORSO); DestroySection(wounded, attacker, 0, RTORSO); DestroySection(wounded, attacker, 0, LLEG); DestroySection(wounded, attacker, 0, RLEG); /* Need to autoeject before the explosion reaches the head */ if (!MapIsUnderground(map)) autoeject(wounded_pilot, wounded, 0); DestroySection(wounded, attacker, 0, HEAD); MechZ(wounded) += 6; dam = MAX(MechTons(wounded) / 5, MechEngineSize(wounded) / 10); ScrambleInfraAndLiteAmp(wounded, 4, 0, "The searing blast of heat burns out your sensors!", "The blinding flash of light overloads your sensors!"); blast_hit_hexesf(map, dam, 3, MAX(MechTons(wounded) / 10, MechEngineSize(wounded) / 25), MechFX(wounded), MechFY(wounded), MechFX(wounded), MechFY(wounded), "%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, 3, 5, 1, 2); MechZ(wounded) = z; headhitmwdamage(wounded, 4); } } void DestroyParts(MECH * attacker, MECH * wounded, int hitloc, int breach, int IsDisable) { float oldjs; int i; int critType; int nhs = 0; int tDoAutoFall = 0; int tNormalizeAllCrits = 0; int tNormalizeLocCrits = 0; int tIsLeg = ((hitloc == RLEG || hitloc == LLEG) || ((hitloc == RARM || hitloc == LARM) && (MechIsQuad(wounded)))); if (!(MechType(wounded) == CLASS_MECH || MechType(wounded) == CLASS_MW || MechType(wounded) == CLASS_BSUIT)) { for (i = 0; i < CritsInLoc(wounded, hitloc); i++) if (GetPartType(wounded, hitloc, i) && !PartIsDestroyed(wounded, hitloc, i)) { if (IsDisable == 1) DisablePart(wounded, hitloc, i); else DestroyPart(wounded, hitloc, i); } return; } oldjs = MechJumpSpeed(wounded); for (i = 0; i < CritsInLoc(wounded, hitloc); i++) if (!PartIsDestroyed(wounded, hitloc, i)) { if (IsDisable == 1) DisablePart(wounded, hitloc, i); else if (PartIsDisabled(wounded, hitloc, i)) { DestroyPart(wounded, hitloc, i); continue; } else DestroyPart(wounded, hitloc, i); critType = GetPartType(wounded, hitloc, i); if (IsSpecial(critType)) { switch (Special2I(critType)) { case UPPER_ACTUATOR: case LOWER_ACTUATOR: case HAND_OR_FOOT_ACTUATOR: tNormalizeLocCrits = 1; break; case SHOULDER_OR_HIP: if (tIsLeg) tNormalizeAllCrits = 1; else tNormalizeLocCrits = 1; break; case HEAT_SINK: if (MechSpecials(wounded) & DOUBLE_HEAT_TECH) { if ((nhs++) % 3 == 2) MechRealNumsinks(wounded)++; } MechRealNumsinks(wounded)--; break; case JUMP_JET: MechJumpSpeed(wounded) -= MP1; if (MechJumpSpeed(wounded) < 0) MechJumpSpeed(wounded) = 0; if (attacker && MechJumpSpeed(wounded) == 0 && Jumping(wounded)) { mech_notify(wounded, MECHALL, "Losing your last Jump Jet you fall from the sky!!!!!"); MechLOSBroadcast(wounded, "falls from the sky!"); MechFalls(wounded, (int) (oldjs * MP_PER_KPH), 0); domino_space(wounded, 2); } break; case ENGINE: if (MechEngineHeat(wounded) < 10) MechEngineHeat(wounded) += 5; else if (MechEngineHeat(wounded) < 15) { MechEngineHeat(wounded) = 15; if (attacker) { mech_notify(wounded, MECHALL, "Your engine is destroyed!!"); if (wounded != attacker) mech_notify(attacker, MECHALL, "You destroy the engine!!"); } check_stackpole(wounded, attacker); DestroyMech(wounded, attacker, 1); } break; case TARGETING_COMPUTER: if (!MechCritStatus(wounded) & TC_DESTROYED) { if (attacker) mech_notify(wounded, MECHALL, "Your Targeting Computer is Destroyed"); MechCritStatus(wounded) |= TC_DESTROYED; } break; } } } if (breach) if (MechType(wounded) == CLASS_VEH_GROUND || MechType(wounded) == CLASS_VEH_NAVAL) DestroyMech(wounded, attacker, 0); if (MechType(wounded) == CLASS_MECH || MechType(wounded) == CLASS_MW) { if (breach && hitloc == HEAD) { if (InVacuum(wounded)) mech_notify(wounded, MECHALL, "You are exposed to vacuum!"); else mech_notify(wounded, MECHALL, "Water floods into your cockpit!"); KillMechContentsIfIC(wounded->mynum); DestroyMech(wounded, attacker, 0); return; } if (!MechIsQuad(wounded)) if (hitloc == LARM || hitloc == RARM) return; if (hitloc == RLEG || hitloc == LLEG || hitloc == LARM || hitloc == RARM) { tDoAutoFall = 1; StopStand(wounded); } if (tNormalizeAllCrits) NormalizeAllActuatorCrits(wounded); else if (tNormalizeLocCrits) NormalizeLocActuatorCrits(wounded, hitloc); if (tIsLeg && !Fallen(wounded) && !Jumping(wounded) && !OODing(wounded) && attacker) { if (tDoAutoFall) { mech_notify(wounded, MECHALL, "You realize remaining standing is no longer an option and crash to the ground!"); MechLOSBroadcast(wounded, "crashes to the ground!"); MechFalls(wounded, 1, 0); } else if (!MadePilotSkillRoll(wounded, 0)) { mech_notify(wounded, MECHALL, "You lose your balance and fall down!"); MechLOSBroadcast(wounded, "loses balance and falls down!"); MechFalls(wounded, 1, 0); } } } } int BreachLoc(MECH * attacker, MECH * mech, int hitloc) { char buf[SBUF_SIZE]; if (!InSpecial(mech)) return 0; if (!InVacuum(mech)) return 0; if (SectIsDestroyed(mech, hitloc) || SectIsBreached(mech, hitloc)) return 0; ArmorStringFromIndex(hitloc, buf, MechType(mech), MechMove(mech)); mech_notify(mech, MECHALL, tprintf("Your %s has been breached!", buf)); SetSectBreached(mech, hitloc); DestroyParts(attacker, mech, hitloc, 1, 1); return 1; } int PossiblyBreach(MECH * attacker, MECH * mech, int hitloc) { if (!InSpecial(mech)) return 0; if (Roll() < 10) return 0; return BreachLoc(attacker, mech, hitloc); }