00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012 #include "mech.events.h"
00013 #include "mech.notify.h"
00014 #include "p.aero.move.h"
00015 #include "p.mech.utils.h"
00016 #include "p.mech.update.h"
00017 #include "p.mech.los.h"
00018 #include "p.btechstats.h"
00019 #include "p.mech.sensor.h"
00020 #include "p.mech.partnames.h"
00021 #include "p.mech.combat.misc.h"
00022
00023 #undef WEAPON_RECYCLE_DEBUG
00024
00025 void mech_heartbeat(MECH *mech) {
00026 UpdateRecycling(mech);
00027 return;
00028 }
00029
00030 static int factoral(int n)
00031 {
00032 int i, j = 0;
00033
00034 for(i = 1; i <= n; i++)
00035 j += i;
00036 return j;
00037 }
00038
00039 void mech_standfail_event(MUXEVENT * e)
00040 {
00041 MECH *mech = (MECH *) e->data;
00042
00043 mech_notify(mech, MECHALL,
00044 "%cgYou have finally recovered from your attempt to stand.%c");
00045 }
00046
00047 void mech_fall_event(MUXEVENT * e)
00048 {
00049 MECH *mech = (MECH *) e->data;
00050 int fallspeed = (int) e->data2;
00051 int fallen_elev;
00052
00053 if(Started(mech) && fallspeed >= 0)
00054 return;
00055 if(fallspeed <= 0 && (!Started(mech) || !(FlyingT(mech)) ||
00056 ((AeroFuel(mech) <= 0) && !AeroFreeFuel(mech)) ||
00057 ((MechType(mech) == CLASS_VTOL) &&
00058 (SectIsDestroyed(mech, ROTOR)))))
00059 fallspeed -= FALL_ACCEL;
00060 else
00061 fallspeed += FALL_ACCEL;
00062 MarkForLOSUpdate(mech);
00063 if(MechsElevation(mech) > abs(fallspeed)) {
00064 MechZ(mech) -= abs(fallspeed);
00065 MechFZ(mech) = MechZ(mech) * ZSCALE;
00066 MECHEVENT(mech, EVENT_FALL, mech_fall_event, FALL_TICK, fallspeed);
00067 return;
00068 }
00069
00070 fallen_elev = factoral(abs(fallspeed));
00071 mech_notify(mech, MECHALL, "You hit the ground!");
00072 MechLOSBroadcast(mech, "hits the ground!");
00073 MechFalls(mech, fallen_elev, 0);
00074 MechStatus(mech) &= ~JUMPING;
00075 }
00076
00077
00078 void mech_lock_event(MUXEVENT * e)
00079 {
00080 MECH *mech = (MECH *) e->data;
00081 MAP *map;
00082 MECH *target;
00083
00084 if(MechTarget(mech) >= 0) {
00085 map = getMap(mech->mapindex);
00086 target = FindObjectsData(MechTarget(mech));
00087 if(!target)
00088 return;
00089 if(!InLineOfSight(mech, target, MechX(target), MechY(target),
00090 FlMechRange(map, mech, target)))
00091 return;
00092 mech_printf(mech, MECHALL,
00093 "The sensors acquire a stable lock on %s.",
00094 GetMechToMechID(mech, target));
00095 } else if(MechTargX(mech) >= 0 && MechTargY(mech) >= 0)
00096 mech_printf(mech, MECHALL,
00097 "The sensors acquire a stable lock on (%d,%d).",
00098 MechTargX(mech), MechTargY(mech));
00099
00100 }
00101
00102
00103
00104
00105 void mech_stabilizing_event(MUXEVENT * e)
00106 {
00107 MECH *mech = (MECH *) e->data;
00108
00109 mech_notify(mech, MECHSTARTED,
00110 "%cgYou have finally stabilized after your jump.%c");
00111 }
00112
00113 void mech_jump_event(MUXEVENT * e)
00114 {
00115 MECH *mech = (MECH *) e->data;
00116
00117 MECHEVENT(mech, EVENT_JUMP, mech_jump_event, JUMP_TICK, 0);
00118 move_mech(mech);
00119 if(!Jumping(mech))
00120 StopJump(mech);
00121 }
00122
00123 extern int PilotStatusRollNeeded[];
00124
00125 void mech_recovery_event(MUXEVENT * e)
00126 {
00127 MECH *mech = (MECH *) e->data;
00128
00129 if(Destroyed(mech) || !Uncon(mech))
00130 return;
00131 if(handlemwconc(mech, 0)) {
00132 MechStatus(mech) &= ~UNCONSCIOUS;
00133 mech_notify(mech, MECHALL, "The pilot regains consciousness!");
00134 return;
00135 }
00136 }
00137
00138 void ProlongUncon(MECH * mech, int len)
00139 {
00140 int l;
00141
00142 if(Destroyed(mech))
00143 return;
00144 if(!Recovering(mech)) {
00145 MechStatus(mech) |= UNCONSCIOUS;
00146 MECHEVENT(mech, EVENT_RECOVERY, mech_recovery_event, len, 0);
00147 return;
00148 }
00149 l = muxevent_last_type_data(EVENT_RECOVERY, (void *) mech) + len;
00150 muxevent_remove_type_data(EVENT_RECOVERY, (void *) mech);
00151 MECHEVENT(mech, EVENT_RECOVERY, mech_recovery_event, l, 0);
00152 }
00153
00154 struct foo {
00155 char *name;
00156 char *full;
00157 int ofs;
00158 };
00159 extern struct foo lateral_modes[];
00160
00161 #ifdef BT_MOVEMENT_MODES
00162 void mech_sideslip_event(MUXEVENT * e)
00163 {
00164 MECH *mech = (MECH *) e->data;
00165 int roll;
00166
00167 if(!mech || !Started(mech))
00168 return;
00169 mech_notify(mech, MECHALL, "You make a skill roll while sideslipping!");
00170 if(!MadePilotSkillRoll
00171 (mech,
00172 HasBoolAdvantage(MechPilot(mech), "maneuvering_ace") ? -1 : 0)) {
00173 mech_notify(mech, MECHALL, "You fail and spin out!");
00174 MechLOSBroadcast(mech, "spins out while sideslipping!");
00175 MechSpeed(mech) = 0.0;
00176 roll = Number(0, 5);
00177 AddFacing(mech, roll * 60);
00178 SetFacing(mech, AcceptableDegree(MechFacing(mech)));
00179 MechDesiredFacing(mech) = MechFacing(mech);
00180 MechDesiredSpeed(mech) = 0.0;
00181 MechLateral(mech) = 0;
00182 return;
00183 }
00184 MECHEVENT(mech, EVENT_SIDESLIP, mech_sideslip_event, TURN, 0);
00185 }
00186 #endif
00187
00188 void mech_lateral_event(MUXEVENT * e)
00189 {
00190 MECH *mech = (MECH *) e->data;
00191 int latmode = (int) e->data2;
00192
00193 if(!mech || !Started(mech))
00194 return;
00195 mech_printf(mech, MECHALL,
00196 "Lateral movement mode change to %s completed.",
00197 lateral_modes[latmode].full);
00198 MechLateral(mech) = lateral_modes[latmode].ofs;
00199 #ifdef BT_MOVEMENT_MODES
00200 if(MechMove(mech) != MOVE_QUAD) {
00201 if(MechLateral(mech) == 0)
00202 StopSideslip(mech);
00203 else if(!(SideSlipping(mech)))
00204 MECHEVENT(mech, EVENT_SIDESLIP, mech_sideslip_event, 1, 0);
00205 }
00206 #endif
00207 }
00208
00209 void mech_move_event(MUXEVENT * e)
00210 {
00211 MECH *mech = (MECH *) e->data;
00212
00213 if(MechType(mech) == CLASS_VTOL)
00214 if(Landed(mech) || FuelCheck(mech))
00215 return;
00216 UpdateHeading(mech);
00217 if((IsMechLegLess(mech)) || Jumping(mech) || OODing(mech)) {
00218 if(MechDesiredFacing(mech) != MechFacing(mech))
00219 MECHEVENT(mech, EVENT_MOVE, mech_move_event, MOVE_TICK, 0);
00220 return;
00221 }
00222 UpdateSpeed(mech);
00223 move_mech(mech);
00224
00225 if(mech->mapindex < 0)
00226 return;
00227
00228 if(MechType(mech) == CLASS_VEH_NAVAL && MechRTerrain(mech) != BRIDGE &&
00229 MechRTerrain(mech) != ICE && MechRTerrain(mech) != WATER)
00230 return;
00231
00232 if(MechSpeed(mech) || MechDesiredSpeed(mech) ||
00233 MechDesiredFacing(mech) != MechFacing(mech) ||
00234 ((MechType(mech) == CLASS_VTOL || MechMove(mech) == MOVE_SUB) &&
00235 MechVerticalSpeed(mech)))
00236 MECHEVENT(mech, EVENT_MOVE, mech_move_event, MOVE_TICK, 0);
00237 }
00238
00239 void mech_stand_event(MUXEVENT * e)
00240 {
00241 MECH *mech = (MECH *) e->data;
00242
00243 MechLOSBroadcast(mech, "stands up!");
00244 mech_notify(mech, MECHALL, "You have finally finished standing up.");
00245 MakeMechStand(mech);
00246 }
00247
00248 void mech_plos_event(MUXEVENT * e)
00249 {
00250 MECH *mech = (MECH *) e->data, *target;
00251 MAP *map;
00252 int mapvis;
00253 int maplight;
00254 float range;
00255 int i;
00256
00257 if(!Started(mech))
00258 return;
00259 if(!(map = getMap(mech->mapindex)))
00260 return;
00261 MECHEVENT(mech, EVENT_PLOS, mech_plos_event, PLOS_TICK, 0);
00262 if(!MechPNumSeen(mech) && !(MechSpecials(mech) & AA_TECH))
00263 return;
00264 mapvis = map->mapvis;
00265 maplight = map->maplight;
00266 MechPNumSeen(mech) = 0;
00267 for(i = 0; i < map->first_free; i++)
00268 if(map->mechsOnMap[i] > 0 && map->mechsOnMap[i] != mech->mynum)
00269 if(!(map->LOSinfo[mech->mapnumber][i] & MECHLOSFLAG_SEEN)) {
00270 target = FindObjectsData(map->mechsOnMap[i]);
00271 if(!target)
00272 continue;
00273 range = FlMechRange(map, mech, target);
00274 MechPNumSeen(mech)++;
00275 Sensor_DoWeSeeNow(mech, &map->LOSinfo[mech->mapnumber][i],
00276 range, -1, -1, target, mapvis, maplight,
00277 map->cloudbase, 1, 0);
00278
00279 }
00280 }
00281
00282 void aero_move_event(MUXEVENT * e)
00283 {
00284 MECH *mech = (MECH *) e->data;
00285
00286 if(!Landed(mech)) {
00287
00288
00289
00290
00291
00292 if(FuelCheck(mech))
00293 return;
00294
00295 if(Started(mech)) {
00296 aero_UpdateHeading(mech);
00297 aero_UpdateSpeed(mech);
00298 }
00299 if(Fallen(mech))
00300 MechStartFZ(mech) = MechStartFZ(mech) - 1;
00301 move_mech(mech);
00302 if(IsDS(mech) && MechZ(mech) <= (MechElevation(mech) + 5) &&
00303 ((muxevent_tick / WEAPON_TICK) % 10) == 0)
00304 DS_BlastNearbyMechsAndTrees(mech,
00305 "You are hit by the DropShip's plasma exhaust!",
00306 "is hit directly by DropShip's exhaust!",
00307 "You are hit by the DropShip's plasma exhaust!",
00308 "is hit by DropShip's exhaust!",
00309 "light up and burn.", 8);
00310 MECHEVENT(mech, EVENT_MOVE, aero_move_event, MOVE_TICK, 0);
00311 } else if(Landed(mech) && !Fallen(mech) && RollingT(mech)) {
00312 UpdateHeading(mech);
00313 UpdateSpeed(mech);
00314 move_mech(mech);
00315 if(fabs(MechSpeed(mech)) > 0.0 ||
00316 fabs(MechDesiredSpeed(mech)) > 0.0 ||
00317 MechDesiredFacing(mech) != MechFacing(mech))
00318 if(!FuelCheck(mech))
00319 MECHEVENT(mech, EVENT_MOVE, aero_move_event, MOVE_TICK, 0);
00320 }
00321 }
00322
00323 void very_fake_func(MUXEVENT * e)
00324 {
00325
00326 }
00327
00328
00329
00330
00331 void mech_crewstun_event(MUXEVENT * e)
00332 {
00333 MECH *mech = (MECH *) e->data;
00334
00335 if(!mech)
00336 return;
00337 if(!Started(mech) || Destroyed(mech)) {
00338 if(MechCritStatus(mech) & MECH_STUNNED)
00339 MechCritStatus(mech) &= ~MECH_STUNNED;
00340 return;
00341 }
00342 if(MechType(mech) != CLASS_MECH)
00343 mech_notify(mech, MECHALL,
00344 "%ch%cgThe crew recovers from their bewilderment!%cn");
00345 else
00346 mech_notify(mech, MECHALL,
00347 "%ch%cgYou recover from your stunning experience!%cn");
00348
00349 if(MechCritStatus(mech) & MECH_STUNNED)
00350 MechCritStatus(mech) &= ~MECH_STUNNED;
00351 }
00352
00353 void unstun_crew_event(MUXEVENT * e)
00354 {
00355 MECH *mech = (MECH *) e->data;
00356
00357 if(CrewStunned(mech) > 1)
00358 return;
00359
00360 mech_notify(mech, MECHALL,
00361 "Your head clears and you're able to control your vehicle again.");
00362 MechTankCritStatus(mech) &= ~CREW_STUNNED;
00363 }
00364
00365 void mech_unjam_ammo_event(MUXEVENT * objEvent)
00366 {
00367 MECH *objMech = (MECH *) objEvent->data;
00368 int wWeapNum = (int) objEvent->data2;
00369 int wSect, wSlot, wWeapStatus, wWeapIdx;
00370 int ammoLoc, ammoCrit,ammoLoc1, ammoCrit1;
00371 int wRoll = 0;
00372 int wRollNeeded = 0;
00373
00374 if(Uncon(objMech) || !Started(objMech))
00375 return;
00376
00377 wWeapStatus = FindWeaponNumberOnMech(objMech, wWeapNum, &wSect, &wSlot);
00378
00379 if(wWeapStatus == TIC_NUM_DESTROYED)
00380 return;
00381
00382 wWeapIdx = FindWeaponIndex(objMech, wWeapNum);
00383
00384 if(!FindAndCheckAmmo(objMech, wWeapIdx, wSect, wSlot, &ammoLoc, &ammoCrit, &ammoLoc1, &ammoCrit1, 0)) {
00385 SetPartTempNuke(objMech, wSect, wSlot, 0);
00386
00387 mech_printf(objMech, MECHALL,
00388 "You finish bouncing around and realize you no longer have ammo for your %s!",
00389 get_parts_long_name(I2Weapon(wWeapIdx), 0));
00390 return;
00391 }
00392
00393 if(MechWeapons[wWeapStatus].special & RAC) {
00394 wRoll = Roll();
00395 wRollNeeded = FindPilotGunnery(objMech, wWeapStatus) + 3;
00396
00397 mech_notify(objMech, MECHPILOT,
00398 "You make a roll to unjam the weapon!");
00399 mech_printf(objMech, MECHPILOT,
00400 "Modified Gunnery Skill: BTH %d\tRoll: %d",
00401 wRollNeeded, wRoll);
00402
00403 if(wRoll < wRollNeeded) {
00404 mech_notify(objMech, MECHALL,
00405 "Your attempt to remove the jammed slug fails. You'll need to try again to clear it.");
00406 return;
00407 }
00408 } else {
00409 if(!MadePilotSkillRoll(objMech, 0)) {
00410 mech_notify(objMech, MECHALL,
00411 "Your attempt to remove the jammed slug fails. You'll need to try again to clear it.");
00412 return;
00413 }
00414 }
00415
00416 SetPartTempNuke(objMech, wSect, wSlot, 0);
00417 mech_printf(objMech, MECHALL,
00418 "You manage to clear the jam on your %s!",
00419 get_parts_long_name(I2Weapon(wWeapIdx), 0));
00420 MechLOSBroadcast(objMech, "ejects a mangled shell!");
00421
00422 decrement_ammunition(objMech, wWeapNum, wSect, wSlot, ammoLoc, ammoCrit, ammoLoc1, ammoCrit1, 0);
00423
00424 }
00425
00426 void check_stagger_event(MUXEVENT * event)
00427 {
00428 MECH *mech = (MECH *) event->data;
00429
00430 SendDebug(tprintf("Triggered stagger check for %d.", mech->mynum));
00431
00432 if((StaggerLevel(mech) < 1) || Fallen(mech) ||
00433 (MechType(mech) != CLASS_MECH)) {
00434 StopStaggerCheck(mech);
00435 return;
00436 }
00437
00438 if(Jumping(mech)) {
00439 return;
00440 }
00441
00442 mech_notify(mech, MECHALL, "You stagger from the damage!");
00443 if(!MadePilotSkillRoll(mech, calcStaggerBTHMod(mech))) {
00444 mech_notify(mech, MECHALL,
00445 "You loose the battle with gravity and tumble over!!");
00446 MechLOSBroadcast(mech, "tumbles over, staggered by the damage!");
00447 MechFalls(mech, 1, 0);
00448 }
00449
00450 StopStaggerCheck(mech);
00451
00452
00453
00454
00455
00456 mech->rd.staggerDamage = -10;
00457 }
00458
00459 #ifdef BT_MOVEMENT_MODES
00460 void mech_movemode_event(MUXEVENT * e)
00461 {
00462 MECH *mech = (MECH *) e->data;
00463 int i = (int) e->data2;
00464 int dir = (i & MODE_ON ? 1 : i & MODE_OFF ? 0 : 0);
00465
00466 if(!mech || !Started(mech) || Destroyed(mech)) {
00467 MechStatus2(mech) &= ~(MOVE_MODES);
00468 return;
00469 }
00470 if(dir) {
00471 if(i & MODE_EVADE) {
00472 MechStatus2(mech) |= EVADING;
00473 mech_notify(mech, MECHALL,
00474 "You bounce chaotically as you maximize your movement mode to evade!");
00475 MechLOSBroadcast(mech,
00476 "suddenly begins to move erratically performing evasive maneuvers!");
00477 } else if(i & MODE_SPRINT) {
00478 MechStatus2(mech) |= SPRINTING;
00479 mech_notify(mech, MECHALL,
00480 "You shimmy side to side as you get more speed from your movement mode.");
00481 if((MechType(mech) == CLASS_MECH)
00482 || (MechType(mech) == CLASS_BSUIT))
00483 MechLOSBroadcast(mech,
00484 "breaks out into a full blown stride as it sprints over the terrain!");
00485 else
00486 MechLOSBroadcast(mech,
00487 "shifts into high gear as it gains more speed!");
00488 if(MechSpeed(mech) < 0) {
00489 mech_notify(mech, MECHALL,
00490 "You stop your backward momemtum while sprinting and come to a stop!");
00491 MechDesiredSpeed(mech) = 0;
00492 }
00493 } else if(i & MODE_DODGE) {
00494 if(MechFullNoRecycle(mech, CHECK_PHYS) > 0) {
00495 mech_notify(mech, MECHALL,
00496 "You cannot enter DODGE mode due to physical useage.");
00497 return;
00498 } else {
00499 MechStatus2(mech) |= DODGING;
00500 mech_notify(mech, MECHALL,
00501 "You brace yourself for any oncoming physicals.");
00502 }
00503 }
00504 } else {
00505 if(i & MODE_EVADE) {
00506 MechStatus2(mech) &= ~EVADING;
00507 mech_notify(mech, MECHALL,
00508 "Cockpit movement normalizes as you cease your evasive maneuvers.");
00509 MechLOSBroadcast(mech,
00510 "ceases its evasive behavior and calms down.");
00511 } else if(i & MODE_SPRINT) {
00512 MechStatus2(mech) &= ~SPRINTING;
00513 mech_notify(mech, MECHALL,
00514 "You feel less seasick as you leave your sprint mode and resume normal movement.");
00515 MechLOSBroadcast(mech,
00516 "slows down and enters a normal movement mode.");
00517 } else if(i & MODE_DODGE) {
00518 MechStatus2(mech) &= ~DODGING;
00519 if(i & MODE_DG_USED)
00520 mech_notify(mech, MECHALL,
00521 "You're dodge maneuver has been used and you are no longer braced for physicals.");
00522 else
00523 mech_notify(mech, MECHALL,
00524 "You loosen up your stance and no longer dodge physicals.");
00525 }
00526 }
00527 if(MechSpeed(mech) > MMaxSpeed(mech)
00528 || MechDesiredSpeed(mech) > MMaxSpeed(mech))
00529 MechDesiredSpeed(mech) = MMaxSpeed(mech);
00530 return;
00531 }
00532 #endif
00533
00534 int calcStaggerBTHMod(MECH * mech)
00535 {
00536 int bthMod = 0;
00537 int tonnageMod = 0;
00538
00539 if(!Started(mech)) {
00540 bthMod = 999;
00541 } else {
00542 bthMod = StaggerLevel(mech);
00543
00544 if(MechTons(mech) <= 35)
00545 tonnageMod = 1;
00546 else if(MechTons(mech) <= 55)
00547 tonnageMod = 0;
00548 else if(MechTons(mech) <= 75)
00549 tonnageMod = -1;
00550 else
00551 tonnageMod = -2;
00552
00553 bthMod += tonnageMod;
00554 }
00555
00556 return bthMod;
00557 }