/* * $Id: mech.ice.c,v 1.1.1.1 2005/01/11 21:18:17 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: Thu Mar 20 20:29:14 1997 fingon * Last modified: Sat Jul 18 02:29:17 1998 fingon * */ #include "mech.h" #include "mech.events.h" #include "p.mech.update.h" #include "p.bsuit.h" #include "p.mech.utils.h" #include "p.mech.pickup.h" #include "p.mech.tag.h" #define TMP_TERR '1' static void swim_except(MAP * map, MECH * mech, int x, int y, char *msg, int isbridge) { int i, j; MECH *t; if (!(Elevation(map, x, y))) return; for (i = 0; i < map->first_free; i++) { j = map->mechsOnMap[i]; if (j < 0) continue; t = getMech(j); if (!t || t == mech) continue; if (MechX(t) != x || MechY(t) != y) continue; MechTerrain(t) = WATER; if ((!isbridge && (MechZ(t) == 0) && (MechMove(t) != MOVE_HOVER)) || (isbridge && MechZ(t) == MechElev(t))) { MechLOSBroadcast(t, msg); MechFalls(t, MechElev(t) + isbridge, 0); if (MechType(t) == CLASS_VEH_GROUND && !Destroyed(t)) { mech_notify(t, MECHALL, "Water renders your vehicle inoperable."); MechLOSBroadcast(t, "fizzles and pops as water renders it inoperable."); Destroy(t); } } } } static void break_sub(MAP * map, MECH * mech, int x, int y, char *msg) { int isbridge = GetRTerrain(map, x, y) == BRIDGE; SetTerrain(map, x, y, WATER); if (isbridge) SetElevation(map, x, y, 1); swim_except(map, mech, x, y, msg, isbridge); } /* Up -> down */ void drop_thru_ice(MECH * mech) { MAP *map = FindObjectsData(mech->mapindex); mech_notify(mech, MECHALL, "You break the ice!"); MechLOSBroadcast(mech, "breaks the ice!"); if (MechMove(mech) != MOVE_FOIL) { if (MechElev(mech) > 0) MechLOSBroadcast(mech, "vanishes into the waters!"); } break_sub(map, mech, MechX(mech), MechY(mech), "goes swimming!"); MechTerrain(mech) = WATER; if (MechMove(mech) != MOVE_FOIL) { if (MechElev(mech) > 0) MechFalls(mech, MechElev(mech), 0); } if (MechElev(mech) > 0 && MechType(mech) == CLASS_VEH_GROUND && !Destroyed(mech)) { mech_notify(mech, MECHALL, "Water renders your vehicle inoperable."); MechLOSBroadcast(mech, "fizzles and pops as water renders it inoperable."); Destroy(mech); } } /* Down -> up */ void break_thru_ice(MECH * mech) { MAP *map = FindObjectsData(mech->mapindex); MarkForLOSUpdate(mech); mech_notify(mech, MECHALL, "You break through the ice!"); MechLOSBroadcast(mech, "breaks through the ice!"); break_sub(map, mech, MechX(mech), MechY(mech), "goes swimming!"); MechTerrain(mech) = WATER; } /* CHANCE of dropping thru the ice based on 'mech weight */ int possibly_drop_thru_ice(MECH * mech) { if ((MechMove(mech) == MOVE_HOVER) || (MechMove(mech) == MOVE_SUB) || (MechType(mech) == CLASS_BSUIT)) return 0; if (Number(1, 6) != 1) return 0; drop_thru_ice(mech); return 1; } static int watercount; static void growable_callback(MAP *map, int x, int y) { int terrain = GetRTerrain(map, x, y); if ((IsWater(terrain) && terrain != ICE) || GetRTerrain(map, x, y) == TMP_TERR) watercount++; } int growable(MAP * map, int x, int y) { watercount = 0; visit_neighbor_hexes(map, x, y, growable_callback); if (watercount <= 4 && (watercount < 2 || (Number(1, 6) > watercount))) return 1; return 0; } static void meltable_callback(MAP * map, int x, int y) { if (GetRTerrain(map, x, y) == ICE) watercount++; } int meltable(MAP * map, int x, int y) { watercount = 0; visit_neighbor_hexes(map, x, y, meltable_callback); if (watercount > 4 && Number(1, 3) > 1) return 0; return 1; } void ice_growth(dbref player, MAP * map, int num) { int x, y; int count = 0; for (x = 0; x < map->map_width; x++) for (y = 0; y < map->map_height; y++) if (GetRTerrain(map, x, y) == WATER) if (Number(1, 100) <= num && growable(map, x, y)) { SetTerrain(map, x, y, TMP_TERR); count++; } for (x = 0; x < map->map_width; x++) for (y = 0; y < map->map_height; y++) if (GetRTerrain(map, x, y) == TMP_TERR) SetTerrain(map, x, y, ICE); if (count) notify(player, tprintf("%d hexes 'iced'.", count)); else notify(player, "No hexes 'iced'."); } void ice_melt(dbref player, MAP * map, int num) { int x, y; int count = 0; for (x = 0; x < map->map_width; x++) for (y = 0; y < map->map_height; y++) if (GetRTerrain(map, x, y) == ICE) if (Number(1, 100) <= num && meltable(map, x, y)) { break_sub(map, NULL, x, y, "goes swimming as ice breaks!"); SetTerrain(map, x, y, TMP_TERR); count++; } for (x = 0; x < map->map_width; x++) for (y = 0; y < map->map_height; y++) if (GetRTerrain(map, x, y) == TMP_TERR) SetTerrain(map, x, y, WATER); if (count) notify(player, tprintf("%d hexes melted.", count)); else notify(player, "No hexes melted."); } void map_addice(dbref player, MAP * map, char *buffer) { char *args[2]; int num; DOCHECK(mech_parseattributes(buffer, args, 2) != 1, "Invalid arguments!"); DOCHECK(Readnum(num, args[0]), "Invalid number!"); ice_growth(player, map, num); } void map_delice(dbref player, MAP * map, char *buffer) { char *args[2]; int num; DOCHECK(mech_parseattributes(buffer, args, 2) != 1, "Invalid arguments!"); DOCHECK(Readnum(num, args[0]), "Invalid number!"); ice_melt(player, map, num); } void possibly_blow_ice(MECH * mech, int weapindx, int x, int y) { MAP *map = FindObjectsData(mech->mapindex); if (GetRTerrain(map, x, y) != ICE) return; if (Number(1, 15) > MechWeapons[weapindx].damage) return; HexLOSBroadcast(map, x, y, "The ice breaks from the blast!"); break_sub(map, NULL, x, y, "goes swimming as ice breaks!"); } void possibly_blow_bridge(MECH * mech, int weapindx, int x, int y) { MAP *map = FindObjectsData(mech->mapindex); if (GetRTerrain(map, x, y) != BRIDGE) return; if (MapBridgesCS(map)) return; if (Number(1, 10 * (1 + GetElev(map, x, y))) > MechWeapons[weapindx].damage) { HexLOSBroadcast(map, x, y, "The bridge at $H shudders from direct hit!"); return; } HexLOSBroadcast(map, x, y, "The bridge at $H is blown apart!"); break_sub(map, NULL, x, y, "goes swimming as the bridge is blown apart!"); }