/* ** Command & Conquer Generals(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // ModelState.h // Basic data types needed for the game engine. This is an extension of BaseType.h. // Author: Michael S. Booth, April 2001 #pragma once #ifndef _ModelState_H_ #define _ModelState_H_ #include "Lib/BaseType.h" #include "Common/INI.h" #include "Common/BitFlags.h" //------------------------------------------------------------------------------------------------- /** THE PROBLEM ----------- -- there are lots of different states. (consider that structures can be: day/night, snow/nosnow, powered/not, garrisoned/empty, damaged/not... you do the math.) -- some states are mutually exclusive (idle vs. moving), others are not (snow/nosnow, day/night). generally, humanoid units have mostly the former, while structure units have mostly the latter. The current ModelState system really only supports the mutually-exclusive states well. -- we'd rather not have to specify every state in the INI files, BUT we do want to be able to intelligently choose the best model for a given state, whether or not a "real" state exists for it. -- it would be desirable to have a unified way of representing "ModelState" so that we don't have multiple similar-yet-different systems. YUCK, WHAT NOW -------------- Let's represent the Model State with two dictinct pieces: -- an "ActionState" piece, representing the mutually-exclusive states, which are almost always an action of some sort -- and a "ConditionState" piece, which is a set of bitflags to indicate the static "condition" of the model. Note that these are usually set independently in code, but they are lumped together in order to determine the actual model to be used. (Let's require all objects would be required to have an "Idle" ActionState, which is the normal, just-sitting there condition.) From a code point of view, this becomes an issue of requesting a certain state, and finding the best-fit match for it. So, what are the rules for finding a good match? -- Action states must match exactly. If the desired action state is not found, then the IDLE state is substituted (but this should generally be considered an error condition). -- Condition states choose the match with the closest match among the "Condition" bits in the INI file, based on satisfying the most of the "required" conditions and the fewest of the "forbidden" conditions. */ //------------------------------------------------------------------------------------------------- // IMPORTANT NOTE: you should endeavor to set up states such that the most "normal" // state is defined by the bit being off. That is, the typical "normal" condition // has all condition flags set to zero. enum ModelConditionFlagType { MODELCONDITION_INVALID = -1, MODELCONDITION_FIRST = 0, // // Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE // existing values! // MODELCONDITION_TOPPLED = MODELCONDITION_FIRST, MODELCONDITION_FRONTCRUSHED, MODELCONDITION_BACKCRUSHED, MODELCONDITION_DAMAGED, MODELCONDITION_REALLY_DAMAGED, MODELCONDITION_RUBBLE, MODELCONDITION_SPECIAL_DAMAGED, MODELCONDITION_NIGHT, MODELCONDITION_SNOW, MODELCONDITION_PARACHUTING, MODELCONDITION_GARRISONED, MODELCONDITION_ENEMYNEAR, MODELCONDITION_WEAPONSET_VETERAN, MODELCONDITION_WEAPONSET_ELITE, MODELCONDITION_WEAPONSET_HERO, MODELCONDITION_WEAPONSET_CRATEUPGRADE_ONE, MODELCONDITION_WEAPONSET_CRATEUPGRADE_TWO, MODELCONDITION_WEAPONSET_PLAYER_UPGRADE, MODELCONDITION_DOOR_1_OPENING, MODELCONDITION_DOOR_1_CLOSING, MODELCONDITION_DOOR_1_WAITING_OPEN, MODELCONDITION_DOOR_1_WAITING_TO_CLOSE, MODELCONDITION_DOOR_2_OPENING, MODELCONDITION_DOOR_2_CLOSING, MODELCONDITION_DOOR_2_WAITING_OPEN, MODELCONDITION_DOOR_2_WAITING_TO_CLOSE, MODELCONDITION_DOOR_3_OPENING, MODELCONDITION_DOOR_3_CLOSING, MODELCONDITION_DOOR_3_WAITING_OPEN, MODELCONDITION_DOOR_3_WAITING_TO_CLOSE, MODELCONDITION_DOOR_4_OPENING, MODELCONDITION_DOOR_4_CLOSING, MODELCONDITION_DOOR_4_WAITING_OPEN, MODELCONDITION_DOOR_4_WAITING_TO_CLOSE, MODELCONDITION_ATTACKING, //Simply set when a unit is fighting -- terrorist moving with a target will flail arms like a psycho. MODELCONDITION_PREATTACK_A, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives). MODELCONDITION_FIRING_A, MODELCONDITION_BETWEEN_FIRING_SHOTS_A, MODELCONDITION_RELOADING_A, MODELCONDITION_PREATTACK_B, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives). MODELCONDITION_FIRING_B, MODELCONDITION_BETWEEN_FIRING_SHOTS_B, MODELCONDITION_RELOADING_B, MODELCONDITION_PREATTACK_C, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives). MODELCONDITION_FIRING_C, MODELCONDITION_BETWEEN_FIRING_SHOTS_C, MODELCONDITION_RELOADING_C, MODELCONDITION_TURRET_ROTATE, MODELCONDITION_POST_COLLAPSE, MODELCONDITION_MOVING, MODELCONDITION_DYING, MODELCONDITION_AWAITING_CONSTRUCTION, MODELCONDITION_PARTIALLY_CONSTRUCTED, MODELCONDITION_ACTIVELY_BEING_CONSTRUCTED, MODELCONDITION_PRONE, MODELCONDITION_FREEFALL, MODELCONDITION_ACTIVELY_CONSTRUCTING, MODELCONDITION_CONSTRUCTION_COMPLETE, MODELCONDITION_RADAR_EXTENDING, MODELCONDITION_RADAR_UPGRADED, MODELCONDITION_PANICKING, // yes, it's spelled with a "k". look it up. MODELCONDITION_AFLAME, MODELCONDITION_SMOLDERING, MODELCONDITION_BURNED, MODELCONDITION_DOCKING, ///< This encloses the whole time you are Entering, Actioning, and Exiting a dock MODELCONDITION_DOCKING_BEGINNING, ///< From Enter to Action MODELCONDITION_DOCKING_ACTIVE, ///< From Action to Exit MODELCONDITION_DOCKING_ENDING, ///< Exit all the way to next enter (use only animations that end with this) MODELCONDITION_CARRYING, MODELCONDITION_FLOODED, MODELCONDITION_LOADED, // loaded woot! ... like a transport is loaded MODELCONDITION_JETAFTERBURNER,// shows "flames" for extra motive force (eg, when taking off) MODELCONDITION_JETEXHAUST, // shows "exhaust" for motive force MODELCONDITION_PACKING, // packs an object MODELCONDITION_UNPACKING, // unpacks an object MODELCONDITION_DEPLOYED, // a deployed object state MODELCONDITION_OVER_WATER, // Units that can go over water want cool effects for doing so MODELCONDITION_POWER_PLANT_UPGRADED, // to show special control rods on the cold fusion plant MODELCONDITION_CLIMBING, //For units climbing up or down cliffs. MODELCONDITION_SOLD, // object is being sold #ifdef ALLOW_SURRENDER MODELCONDITION_SURRENDER, //When units surrender... #endif MODELCONDITION_RAPPELLING, MODELCONDITION_ARMED, // armed like a mine or bomb is armed (not like a human is armed) MODELCONDITION_POWER_PLANT_UPGRADING, // while special control rods on the cold fusion plant are extending //Special model conditions work as following: //Something turns it on... but a timer in the object will turn them off after a given //amount of time. If you add any more special animations, then you'll need to add the //code to turn off the state. MODELCONDITION_SPECIAL_CHEERING, //When units do a victory cheer (or player initiated cheer). MODELCONDITION_CONTINUOUS_FIRE_SLOW, MODELCONDITION_CONTINUOUS_FIRE_MEAN, MODELCONDITION_CONTINUOUS_FIRE_FAST, MODELCONDITION_RAISING_FLAG, MODELCONDITION_CAPTURED, MODELCONDITION_EXPLODED_FLAILING, MODELCONDITION_EXPLODED_BOUNCING, MODELCONDITION_SPLATTED, // this is an easier-to-use variant on the whole FIRING_A deal... // these bits are set if firing, reloading, between shots, or preattack. MODELCONDITION_USING_WEAPON_A, MODELCONDITION_USING_WEAPON_B, MODELCONDITION_USING_WEAPON_C, MODELCONDITION_PREORDER, // // Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE // existing values! // MODELCONDITION_COUNT // keep last! }; //------------------------------------------------------------------------------------------------- typedef BitFlags ModelConditionFlags; #define MAKE_MODELCONDITION_MASK(k) ModelConditionFlags(ModelConditionFlags::kInit, (k)) #define MAKE_MODELCONDITION_MASK2(k,a) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a)) #define MAKE_MODELCONDITION_MASK3(k,a,b) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b)) #define MAKE_MODELCONDITION_MASK4(k,a,b,c) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b), (c)) #define MAKE_MODELCONDITION_MASK5(k,a,b,c,d) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b), (c), (d)) #define MAKE_MODELCONDITION_MASK12(a,b,c,d,e,f,g,h,i,j,k,l) ModelConditionFlags(ModelConditionFlags::kInit, (a), (b), (c), (d), (e), (f), (g), (h), (i), (j), (k), (l)) //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- #endif // _ModelState_H_