CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

TRIGGER.CPP (27860B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/TRIGGER.CPP 1     3/03/97 10:26a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : TRIGGER.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 11/12/94                                                     *
     28  *                                                                                             *
     29  *                  Last Update : August 13, 1996 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Find_Or_Make -- Find or create a trigger of the type specified.                           *
     34  *   TriggerClass::As_Target -- Converts trigger to a target value                             *
     35  *   TriggerClass::Attaches_To -- Determines what trigger can attach to.                       *
     36  *   TriggerClass::Description -- Fetch a one line ASCII description of the trigger.           *
     37  *   TriggerClass::Detach -- Detach specified target from this trigger.                        *
     38  *   TriggerClass::Draw_It -- Draws this trigger as if it were part of a list box.             *
     39  *   TriggerClass::Init -- clears triggers for new scenario                                    *
     40  *   TriggerClass::Spring -- Spring the trigger (possibly).                                    *
     41  *   TriggerClass::TriggerClass -- constructor                                                 *
     42  *   TriggerClass::operator delete -- Returns a trigger to the special memory pool.            *
     43  *   TriggerClass::operator new -- 'new' operator                                              *
     44  *   TriggerClass::~TriggerClass -- Destructor for trigger objects.                            *
     45  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     46 
     47 #include "function.h"
     48 
     49 
     50 #if defined(CHEAT_KEYS) || defined(SCENARIO_EDITOR)
     51 /***********************************************************************************************
     52  * TriggerClass::Description -- Fetch a one line ASCII description of the trigger.             *
     53  *                                                                                             *
     54  *    In the rare (possibly never?) case of requiring a description for this trigger, then     *
     55  *    just have the model class generate a description and return that.                        *
     56  *                                                                                             *
     57  * INPUT:   none                                                                               *
     58  *                                                                                             *
     59  * OUTPUT:  Returns with an ASCII description of this trigger.                                 *
     60  *                                                                                             *
     61  * WARNINGS:   see TriggerTypeClass::Description()                                             *
     62  *                                                                                             *
     63  * HISTORY:                                                                                    *
     64  *   07/09/1996 JLB : Created.                                                                 *
     65  *=============================================================================================*/
     66 char const * TriggerClass::Description(void) const
     67 {
     68 	return(Class->Description());
     69 }
     70 
     71 
     72 /***********************************************************************************************
     73  * TriggerClass::Draw_It -- Draws this trigger as if it were part of a list box.               *
     74  *                                                                                             *
     75  *    This routine is called when the trigger has been assigned to a list box. It will         *
     76  *    display a description of the trigger.                                                    *
     77  *                                                                                             *
     78  * INPUT:   see below...                                                                       *
     79  *                                                                                             *
     80  * OUTPUT:  none                                                                               *
     81  *                                                                                             *
     82  * WARNINGS:   none                                                                            *
     83  *                                                                                             *
     84  * HISTORY:                                                                                    *
     85  *   07/09/1996 JLB : Created.                                                                 *
     86  *=============================================================================================*/
     87 void TriggerClass::Draw_It(int , int x, int y, int width, int height, bool selected, TextPrintType flags) const
     88 {
     89 	RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
     90 	static int _tabs[] = {13,40};
     91 	if ((flags & 0x0F) == TPF_6PT_GRAD || (flags & 0x0F) == TPF_EFNT) {
     92 
     93 		if (selected) {
     94 			flags = flags | TPF_BRIGHT_COLOR;
     95 			LogicPage->Fill_Rect(x, y, x + width - 1, y + height - 1, scheme->Shadow);
     96 		} else {
     97 			if (!(flags & TPF_USE_GRAD_PAL)) {
     98 				flags = flags | TPF_MEDIUM_COLOR;
     99 			}
    100 		}
    101 
    102 		Conquer_Clip_Text_Print(Description(), x, y, scheme, TBLACK, flags, width, _tabs);
    103 	} else {
    104 		Conquer_Clip_Text_Print(Description(), x, y, (selected ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY]), TBLACK, flags, width, _tabs);
    105 	}
    106 }
    107 #endif
    108 
    109 
    110 /***********************************************************************************************
    111  * TriggerClass::TriggerClass -- constructor                                                   *
    112  *                                                                                             *
    113  * INPUT:                                                                                      *
    114  *      none.                                                                                  *
    115  *                                                                                             *
    116  * OUTPUT:                                                                                     *
    117  *      none.                                                                                  *
    118  *                                                                                             *
    119  * WARNINGS:                                                                                   *
    120  *      none.                                                                                  *
    121  *                                                                                             *
    122  * HISTORY:                                                                                    *
    123  *   11/28/1994 BR : Created.                                                                  *
    124  *=============================================================================================*/
    125 TriggerClass::TriggerClass(TriggerTypeClass * trigtype) :
    126 	RTTI(RTTI_TRIGGER),
    127 	ID(Triggers.ID(this)),
    128 	Class(trigtype),
    129 	AttachCount(0),
    130 	Cell(0)
    131 {
    132 	Class->Event1.Reset(Event1);
    133 	Class->Event2.Reset(Event2);
    134 }
    135 
    136 
    137 /***********************************************************************************************
    138  * TriggerClass::~TriggerClass -- Destructor for trigger objects.                              *
    139  *                                                                                             *
    140  *    This destructor will update the house blockage value if necessary. No other action need  *
    141  *    be performed on trigger destruction.                                                     *
    142  *                                                                                             *
    143  * INPUT:   none                                                                               *
    144  *                                                                                             *
    145  * OUTPUT:  none                                                                               *
    146  *                                                                                             *
    147  * WARNINGS:   none                                                                            *
    148  *                                                                                             *
    149  * HISTORY:                                                                                    *
    150  *   07/29/1995 JLB : Created.                                                                 *
    151  *=============================================================================================*/
    152 TriggerClass::~TriggerClass(void)
    153 {
    154 	if (GameActive && Class.Is_Valid() && (Class->Attaches_To() & ATTACH_GENERAL) != 0) {
    155 		if (LogicTriggerID >= LogicTriggers.ID(this)) {
    156 			LogicTriggerID--;
    157 			if (LogicTriggerID < 0 && LogicTriggers.Count() == 0) {
    158 				LogicTriggerID = 0;
    159 			}
    160 		}
    161 	}
    162 
    163 	if (GameActive && Class.Is_Valid() && (Class->Attaches_To() & ATTACH_MAP) != 0) {
    164 		if (MapTriggerID >= MapTriggers.ID(this)) {
    165 			MapTriggerID--;
    166 			if (MapTriggerID < 0 && MapTriggers.Count() == 0) {
    167 				MapTriggerID = 0;
    168 			}
    169 		}
    170 	}
    171 
    172 	if (GameActive && Class->House != HOUSE_NONE && Class->Action1.Action == TACTION_ALLOWWIN) {
    173 		if (Houses.Ptr(Class->House)->Blockage) Houses.Ptr(Class->House)->Blockage--;
    174 		Houses.Ptr(Class->House)->BorrowedTime = TICKS_PER_SECOND*4;
    175 	}
    176 	ID = -1;
    177 }
    178 
    179 
    180 /***********************************************************************************************
    181  * TriggerClass::Init -- clears triggers for new scenario                                      *
    182  *                                                                                             *
    183  * INPUT:                                                                                      *
    184  *      none.                                                                                  *
    185  *                                                                                             *
    186  * OUTPUT:                                                                                     *
    187  *      none.                                                                                  *
    188  *                                                                                             *
    189  * WARNINGS:                                                                                   *
    190  *      none.                                                                                  *
    191  *                                                                                             *
    192  * HISTORY:                                                                                    *
    193  *   11/29/1994 BR : Created.                                                                  *
    194  *=============================================================================================*/
    195 void TriggerClass::Init(void)
    196 {
    197 	Triggers.Free_All();
    198 }
    199 
    200 
    201 /***********************************************************************************************
    202  * TriggerClass::Spring -- Spring the trigger (possibly).                                      *
    203  *                                                                                             *
    204  *    This routine is called when a potential trigger even has occurred. The event is matched  *
    205  *    with the trigger event needed by this trigger. If the condition warrants, the trigger    *
    206  *    action is performed.                                                                     *
    207  *                                                                                             *
    208  * INPUT:   event    -- The event that is occurring.                                           *
    209  *                                                                                             *
    210  *          obj      -- If the trigger is attached to an object, this points to the object.    *
    211  *                                                                                             *
    212  *          cell     -- If the trigger is attached to a cell, this is the cell number.         *
    213  *                                                                                             *
    214  *          forced   -- Should the trigger be forced to execute regardless of the event?       *
    215  *                                                                                             *
    216  * OUTPUT:  bool; Was the trigger sprung?                                                      *
    217  *                                                                                             *
    218  * WARNINGS:   none                                                                            *
    219  *                                                                                             *
    220  * HISTORY:                                                                                    *
    221  *   05/31/1996 JLB : Created.                                                                 *
    222  *   08/13/1996 JLB : Linked triggers supported.                                               *
    223  *=============================================================================================*/
    224 bool TriggerClass::Spring(TEventType event, ObjectClass * obj, CELL cell, bool forced)
    225 {
    226 	assert(Triggers.ID(this) == ID);
    227 
    228 	bool e1 = Class->Event1(Event1, event, Class->House, obj, forced);
    229 	bool e2 = false;
    230 	bool execute = false;
    231 
    232 	/*
    233 	**	Forced triggers must presume that the cell parameter is invalid. It then
    234 	**	uses the embedded cell value in the trigger as the official location where
    235 	**	the trigger will detonate at.
    236 	*/
    237 	if (forced) {
    238 		cell = Cell;
    239 	} else {
    240 
    241 		/*
    242 		**	Determine if the trigger event is considered to have been sprung according to the
    243 		**	event control value. This might require that both events be triggered, one event
    244 		**	triggered, or either event triggered to activate the trigger action.
    245 		*/
    246 		switch (Class->EventControl) {
    247 			case MULTI_ONLY:
    248 				execute = e1;
    249 				break;
    250 
    251 			case MULTI_AND:
    252 				e2 = Class->Event2(Event2, event, Class->House, obj, forced);
    253 				execute = (e1 && e2);
    254 				break;
    255 
    256 			case MULTI_LINKED:
    257 			case MULTI_OR:
    258 				e2 = Class->Event2(Event2, event, Class->House, obj, forced);
    259 				execute = (e1 || e2);
    260 				break;
    261 		}
    262 	}
    263 
    264 	/*
    265 	**	See if the trigger is sprung with a qualifying event.
    266 	*/
    267 	if (execute || forced) {
    268 
    269 		/*
    270 		**	Verify that the trigger event should really be sprung. Exceptions
    271 		**	would include semi-persistent triggers that don't actually
    272 		**	spring until all triggers have sprung.
    273 		*/
    274 		if (Class->IsPersistant == TriggerTypeClass::SEMIPERSISTANT) {
    275 
    276 			/*
    277 			** Detach ourselves from the object and record that there
    278 			**	is one less attachment to keep track of.
    279 			*/
    280 			if (obj) {
    281 				obj->Trigger = NULL;
    282 			}
    283 			if (cell) {
    284 				Map[cell].Trigger = NULL;
    285 			}
    286 
    287 			/*
    288 			** If we're attached to more objects, don't spring; otherwise, spring.
    289 			** And, mark ourselves as volatile so we'll completely remove ourselves
    290 			** from the game after we go off.
    291 			*/
    292 			AttachCount--;
    293 			if (AttachCount > 0) {
    294 				return(false);
    295 			}
    296 		}
    297 
    298 		/*
    299 		**	For linked trigger events, perform the action associated with the matching
    300 		**	trigger event. Otherwise perform the action for both events.
    301 		*/
    302 		bool ok = false;
    303 		HousesType hh = Class->House;
    304 		if (Class->EventControl == MULTI_LINKED) {
    305 			if (e1 || forced) ok |= Class->Action1(hh, obj, ID, cell);
    306 			if (e2 && !forced) ok |= Class->Action2(hh, obj, ID, cell);
    307 		} else {
    308 
    309 			switch (Class->ActionControl) {
    310 				case MULTI_ONLY:
    311 					ok |= Class->Action1(hh, obj, ID, cell);
    312 					break;
    313 
    314 				default:
    315 				case MULTI_AND:
    316 					ok |= Class->Action1(hh, obj, ID, cell);
    317 					ok |= Class->Action2(hh, obj, ID, cell);
    318 					break;
    319 			}
    320 		}
    321 		if (!IsActive) return(true);
    322 
    323 		/*
    324 		**	If at least one action was performed, then consider this
    325 		**	trigger to have completed and thus will be deleted if
    326 		**	necessary.
    327 		*/
    328 		if (ok) {
    329 			#ifdef CHEAT_KEYS
    330 			MonoArray[DMONO_STRESS].Sub_Window(61, 1, 17, 11);
    331 			MonoArray[DMONO_STRESS].Scroll();
    332 			MonoArray[DMONO_STRESS].Sub_Window(61, 1, 18, 11);
    333 			MonoArray[DMONO_STRESS].Set_Cursor(0, 10);
    334 			MonoArray[DMONO_STRESS].Printf("%02d:%02d:%02d-%s", Scen.Timer / TICKS_PER_HOUR, (Scen.Timer % TICKS_PER_HOUR)/TICKS_PER_MINUTE, (Scen.Timer % TICKS_PER_MINUTE)/TICKS_PER_SECOND, Class->IniName);
    335 			MonoArray[DMONO_STRESS].Sub_Window();
    336 			#endif
    337 
    338 			if (Class->IsPersistant == TriggerTypeClass::VOLATILE || (Class->IsPersistant == TriggerTypeClass::SEMIPERSISTANT && AttachCount <= 1)) {
    339 				Detach_This_From_All(As_Target(), true);
    340 				delete this;
    341 				return(true);
    342 			} else {
    343 
    344 				/*
    345 				**	Reset event data so that the event will
    346 				**	repeat as necessary.
    347 				*/
    348 				Class->Event1.Reset(Event1);
    349 				Class->Event2.Reset(Event2);
    350 			}
    351 		}
    352 	}
    353 
    354 	return(false);
    355 }
    356 
    357 
    358 /***********************************************************************************************
    359  * TriggerClass::operator new -- 'new' operator                                                *
    360  *                                                                                             *
    361  * INPUT:                                                                                      *
    362  *      none.                                                                                  *
    363  *                                                                                             *
    364  * OUTPUT:                                                                                     *
    365  *      pointer to new trigger                                                                 *
    366  *                                                                                             *
    367  * WARNINGS:                                                                                   *
    368  *      none.                                                                                  *
    369  *                                                                                             *
    370  * HISTORY:                                                                                    *
    371  *   11/28/1994 BR : Created.                                                                  *
    372  *=============================================================================================*/
    373 void * TriggerClass::operator new(size_t )
    374 {
    375 	void * ptr = Triggers.Allocate();
    376 	if (ptr) {
    377 		((TriggerClass *)ptr)->IsActive = true;
    378 	}
    379 
    380 	return(ptr);
    381 }
    382 
    383 
    384 /***********************************************************************************************
    385  * TriggerClass::operator delete -- Returns a trigger to the special memory pool.              *
    386  *                                                                                             *
    387  *    This routine will return a previously allocated trigger object back to the memory        *
    388  *    pool from which it came.                                                                 *
    389  *                                                                                             *
    390  * INPUT:   pointer  -- Pointer to the trigger to return to the memory pool.                   *
    391  *                                                                                             *
    392  * OUTPUT:  none                                                                               *
    393  *                                                                                             *
    394  * WARNINGS:   none                                                                            *
    395  *                                                                                             *
    396  * HISTORY:                                                                                    *
    397  *   07/09/1996 JLB : Created.                                                                 *
    398  *=============================================================================================*/
    399 void TriggerClass::operator delete(void * pointer)
    400 {
    401 	if (pointer) {
    402 		((TriggerClass *)pointer)->IsActive = false;
    403 	}
    404 	Triggers.Free((TriggerClass *)pointer);
    405 }
    406 
    407 
    408 /***********************************************************************************************
    409  * TriggerClass::As_Target -- Converts trigger to a target value                               *
    410  *                                                                                             *
    411  *    Converts the trigger object into a target identifier.                                    *
    412  *                                                                                             *
    413  * INPUT:   none                                                                               *
    414  *                                                                                             *
    415  * OUTPUT:  TARGET value                                                                       *
    416  *                                                                                             *
    417  * WARNINGS:   none                                                                            *
    418  *                                                                                             *
    419  * HISTORY:                                                                                    *
    420  *   09/19/1994 JLB : Created.                                                                 *
    421  *=============================================================================================*/
    422 TARGET TriggerClass::As_Target(void) const
    423 {
    424 	assert(Triggers.ID(this) == ID);
    425 
    426 	return(Build_Target(RTTI_TRIGGER, ID));
    427 }
    428 
    429 
    430 /***********************************************************************************************
    431  * Find_Or_Make -- Find or create a trigger of the type specified.                             *
    432  *                                                                                             *
    433  *    This routine is used when, given a trigger type, an actual trigger object is needed.     *
    434  *    In this case, an existing trigger of the correct type must be located, or a trigger      *
    435  *    object must be created. In either case, this routine will return a trigger object that   *
    436  *    corresponds to the trigger type class specified.                                         *
    437  *                                                                                             *
    438  * INPUT:   trigtype -- Pointer to the trigger type to find (or create) a matching trigger     *
    439  *                      object.                                                                *
    440  *                                                                                             *
    441  * OUTPUT:  Returns a pointer to a matching trigger object. If no more triggers could be       *
    442  *          allocated and no matching trigger could be found, then this routine will return    *
    443  *          NULL (a very rare case).                                                           *
    444  *                                                                                             *
    445  * WARNINGS:   This routine could return NULL.                                                 *
    446  *                                                                                             *
    447  * HISTORY:                                                                                    *
    448  *   07/09/1996 JLB : Created.                                                                 *
    449  *=============================================================================================*/
    450 TriggerClass * Find_Or_Make(TriggerTypeClass * trigtype)
    451 {
    452 	if (!trigtype) return(NULL);
    453 
    454 	for (int index = 0; index < Triggers.Count(); index++) {
    455 		if (trigtype == Triggers.Ptr(index)->Class) {
    456 			return(Triggers.Ptr(index));
    457 		}
    458 	}
    459 
    460 	/*
    461 	**	No trigger was found, so make one.
    462 	*/
    463 	TriggerClass * trig = new TriggerClass(trigtype);
    464 	return(trig);
    465 }
    466 
    467 
    468 /***********************************************************************************************
    469  * TriggerClass::Detach -- Detach specified target from this trigger.                          *
    470  *                                                                                             *
    471  *    This routine is called when the specified trigger MUST be detached from all references   *
    472  *    to it. The only reference maintained by a trigger is the reference to the trigger        *
    473  *    type class it is modeled after.                                                          *
    474  *                                                                                             *
    475  * INPUT:   target   -- The target identifier to remove all attachments to.                    *
    476  *                                                                                             *
    477  * OUTPUT:  none                                                                               *
    478  *                                                                                             *
    479  * WARNINGS:   You must never detach the trigger type class from a trigger. Such a process     *
    480  *             will leave the trigger orphan and in a 'crash the game immediately if used'     *
    481  *             state. As such, this routine will throw an assertion if this is tried.          *
    482  *                                                                                             *
    483  * HISTORY:                                                                                    *
    484  *   07/09/1996 JLB : Created.                                                                 *
    485  *=============================================================================================*/
    486 void TriggerClass::Detach(TARGET target, bool )
    487 {
    488 	if (Is_Target_TriggerType(target)) {
    489 		assert((TriggerTypeClass*)Class != As_TriggerType(target));
    490 //		if (Class == As_TriggerType(target)) {
    491 //			Class = NULL;
    492 //		}
    493 	}
    494 }