| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /*************************************************************************************
- ** 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 **
- *************************************************************************************
- * *
- * Project Name : Command & Conquer - Red Alert *
- * *
- * File Name : VORTEX.CPP *
- * *
- * Programmer : Steve Tall *
- * *
- * Start Date : August 12th, 1996 *
- * *
- * Last Update : September 6th, 1996 [ST] *
- * *
- *-----------------------------------------------------------------------------------*
- * Overview: *
- * *
- * Circley vortexy swirly type thing. (Really just a pixel & color remap). *
- * *
- *-----------------------------------------------------------------------------------*
- * Functions: *
- * *
- * CVC::ChronalVortexClass -- vortex class constructor *
- * CVC::~ChronalVortexClass -- vortex class destructor *
- * CVC::Appear -- Makes a chronal vortex appear at the given coordinate. *
- * CVC::Disappear -- Makes the chronal vortex go away. *
- * CVC::Hide -- Makes the vortex hide. It might come back later. *
- * CVC::Show -- Makes a hidden vortex visible again. *
- * CVC::Stop -- Stops the vortex without going through the hide animation *
- * CVC::Load -- Loads the chronal vortex from a savegame file. *
- * CVC::Save -- Saves the vortex class data to a savegame file *
- * CVC::AI -- AI for the vortex. Includes movement and firing. *
- * CVC::Movement -- Movement AI for the vortex. *
- * CVC::Set_Target -- Make the vortex zap a particular object. *
- * CVC::Attack -- look for objects to attack *
- * CVC::Zap_Target -- If the vortex has a target object then zap it with lightning. *
- * CVC::Coordinate_Remap -- Draws the vortex *
- * CVC::Render -- Renders the vortex at its current position. *
- * CVC::Set_Redraw -- Flags the cells under to vortex to redraw. *
- * CVC::Setup_Remap_Tables -- Initialises the color remap tables based on theater. *
- * CVC::Build_Fading_Table -- Builds a fading color lookup table. *
- * *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "vortex.h"
- /*
- ** Instance of chronal vortex class. This must be the only instance.
- */
- ChronalVortexClass ChronalVortex;
- /***********************************************************************************************
- * CVC::ChronalVortexClass -- vortex class constructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:25PM ST : Created *
- *=============================================================================================*/
- ChronalVortexClass::ChronalVortexClass (void)
- {
- Active = 0;
- Theater = THEATER_NONE;
- Speed = 10;
- Range = 10;
- Damage = 200;
- RenderBuffer = NULL; //We havn't allocated it yet. It will be allocated as needed.
- }
- /***********************************************************************************************
- * CVC::~ChronalVortexClass -- vortex class destructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:25PM ST : Created *
- *=============================================================================================*/
- ChronalVortexClass::~ChronalVortexClass (void)
- {
- if (RenderBuffer) delete RenderBuffer;
- Active = 0;
- }
- /***********************************************************************************************
- * CVC::Appear -- Makes a chronal vortex appear at the given coordinate. *
- * *
- * *
- * *
- * INPUT: Coordinate that vortex should appear at. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: This member does nothing if the vortex is already active *
- * *
- * HISTORY: *
- * 8/29/96 4:27PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Appear (COORDINATE coordinate)
- {
- if (Active) return;
- /*
- ** Adjust the given coordinate so the vortex appears in a central position
- */
- int x = Lepton_To_Pixel(Coord_X(coordinate));
- int y = Lepton_To_Pixel(Coord_Y(coordinate));
- x -= 32;
- y -= 32;
- LEPTON lx = Pixel_To_Lepton (x);
- LEPTON ly = Pixel_To_Lepton (y);
- Position = XY_Coord (lx, ly);
- /*
- ** Initialise the vortex variables.
- */
- AnimateDir = 1;
- AnimateFrame = 0;
- State = STATE_GROW;
- Active = true;
- Animate = 0;
- StartShutdown = false;
- LastAttackFrame= Frame;
- TargetObject = TARGET_NONE;
- ZapFrame = 0;
- Hidden = false;
- StartHiding = false;
- XDir = 0;
- YDir = 0;
- /*
- ** Vortex starts off in a random direction.
- */
- DesiredXDir = Random_Pick (-Speed, Speed);
- DesiredYDir = Random_Pick (-Speed, Speed);
- }
- /***********************************************************************************************
- * CVC::Disappear -- Makes the chronal vortex go away. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:30PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Disappear (void)
- {
- if (Hidden) {
- Active = false;
- } else {
- StartShutdown = true;
- }
- }
- /***********************************************************************************************
- * CVC::Hide -- Makes the vortex hide. It might come back later. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: This doesnt deactivate the vortex. Use Disappear to get rid of it permanently. *
- * *
- * HISTORY: *
- * 8/29/96 4:30PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Hide (void)
- {
- if (!StartShutdown) {
- StartHiding = true;
- }
- }
- /***********************************************************************************************
- * CVC::Show -- Makes a hidden vortex visible again. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:31PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Show (void)
- {
- /*
- ** Dont do anything if vortx is dying.
- */
- if (!StartShutdown) {
- /*
- ** If the vortex is hidden then show it again.
- */
- if (Hidden) {
- Hidden = false;
- StartHiding = false;
- AnimateFrame = 0;
- State = STATE_GROW;
- XDir = 0;
- YDir = 0;
- } else {
- /*
- ** If the vortex is in the process of hiding then reverse it.
- */
- StartHiding = false;
- if (State == STATE_SHRINK) {
- State = STATE_GROW;
- AnimateFrame = VORTEX_FRAMES - AnimateFrame;
- }
- }
- }
- }
- /***********************************************************************************************
- * CVC::Stop -- Stops the vortex without going through the hide animation *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:32PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Stop(void)
- {
- if (Active) Active = false;
- }
- /***********************************************************************************************
- * CVC::Load -- Loads the chronal vortex from a savegame file. *
- * *
- * *
- * *
- * INPUT: ptr to file *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:32PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Load(Straw &file)
- {
- /*
- ** Delete the render buffer as we are going to lose the pointer anyway.
- ** It will be re-allocated when needed.
- */
- if (RenderBuffer) delete RenderBuffer;
- file.Get (this, sizeof (ChronalVortexClass));
- }
- /***********************************************************************************************
- * CVC::Save -- Saves the vortex class data to a savegame file *
- * *
- * *
- * *
- * INPUT: file *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:33PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Save(Pipe &file)
- {
- GraphicBufferClass *save_ptr = NULL;
- if (RenderBuffer){
- /*
- ** Save the ptr to the render buffer so we can null it for the save
- */
- save_ptr = RenderBuffer;
- RenderBuffer = NULL;
- }
- file.Put (this, sizeof (ChronalVortexClass));
- /*
- ** Restore the render buffer ptr
- */
- if (save_ptr){
- RenderBuffer = save_ptr;
- }
- }
- /***********************************************************************************************
- * CVC::AI -- AI for the vortex. Includes movement and firing. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:34PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::AI(void)
- {
- int chance;
- /*
- ** No AI if vortex isnt active
- */
- if (Active) {
- /*
- ** Do the movement AI
- */
- Movement();
- /*
- ** Do the attack AI
- */
- Zap_Target();
- if (Hidden && (Frame - HiddenFrame > 50) ) {
- /*
- ** Vortex is hidden. Chance of it showing itself increases the longer its stays hidden.
- */
- chance = Random_Pick(0,2000);
- if (chance <= Frame - HiddenFrame) {
- Show();
- }
- } else {
- if (Animate == 0) {
- /*
- ** Its time to animate the vortex.
- */
- AnimateFrame += AnimateDir;
- if (AnimateFrame > VORTEX_FRAMES) {
- /*
- ** State changes can only occur on final animation frames.
- */
- AnimateFrame = 1;
- if (StartShutdown) {
- /*
- ** Vortex is in the process of dying.
- */
- if (State == STATE_SHRINK) {
- Set_Redraw();
- Active = false;
- AnimateFrame = 0;
- } else {
- Attack();
- State = STATE_SHRINK;
- }
- } else {
- if (StartHiding) {
- /*
- ** Vortex wants to hide.
- */
- if (State == STATE_SHRINK) {
- /*
- ** Hide the vortex now.
- */
- Set_Redraw();
- StartHiding = false;
- Hidden = true;
- HiddenFrame = Frame;
- if (Random_Pick(0,4) == 4) {
- Disappear();
- }
- } else {
- /*
- ** Start hiding the vortex.
- */
- Attack();
- State = STATE_SHRINK;
- }
- } else {
- Attack();
- if (State == STATE_GROW) {
- State = STATE_ROTATE;
- } else {
- //Attack();
- }
- }
- }
- } else {
- if (AnimateFrame == VORTEX_FRAMES / 2) Attack();
- }
- }
- Animate++;
- Animate &= 1;
- }
- }
- }
- /***********************************************************************************************
- * CVC::Movement -- Movement AI for the vortex. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:39PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Movement (void)
- {
- bool newpick = true;
- /*
- ** Update the vortex position by applying the x and y direction variables
- */
- LEPTON x = Coord_X(Position);
- LEPTON y = Coord_Y(Position);
- x += XDir;
- y += YDir;
- Position = XY_Coord (x,y);
- /*
- ** Reverse the direction of the vortex if its drifting off the map.
- */
- if (x > CELL_LEPTON_W *(Map.MapCellX + Map.MapCellWidth -4)) {
- newpick = false;
- if (DesiredXDir >0 ) DesiredXDir = -DesiredXDir;
- }
- if (y > CELL_LEPTON_H *(Map.MapCellY + Map.MapCellHeight -4)) {
- newpick = false;
- if (DesiredYDir >0 ) DesiredYDir = -DesiredYDir;
- }
- if (x < CELL_LEPTON_W *Map.MapCellX + 2*CELL_LEPTON_W) {
- newpick = false;
- if (DesiredXDir <0 ) DesiredXDir = -DesiredXDir;
- }
- if (y < CELL_LEPTON_H *Map.MapCellY + 2*CELL_LEPTON_W) {
- newpick = false;
- if (DesiredYDir <0 ) DesiredYDir = -DesiredYDir;
- }
- /*
- ** Vortex direction tends towards the desired direction unless the vortex is shutting down or
- ** appearing in which case the direction tends towards 0.
- */
- if (State == STATE_ROTATE || Hidden) {
- if (XDir < DesiredXDir) XDir ++;
- if (XDir > DesiredXDir) XDir --;
- if (YDir < DesiredYDir) YDir ++;
- if (YDir > DesiredYDir) YDir --;
- } else {
- if (XDir > 0) XDir -= Speed/8;
- if (XDir < 0) XDir += Speed/8;
- if (YDir > 0) YDir -= Speed/8;
- if (YDir < 0) YDir += Speed/8;
- }
- /*
- ** Occasionally change the direction of the vortex.
- */
- if (newpick && Random_Pick (0, 100) == 100) {
- DesiredXDir = Random_Pick (-Speed, Speed);
- DesiredYDir = Random_Pick (-Speed, Speed);
- }
- }
- /***********************************************************************************************
- * CVC::Set_Target -- Make the vortex zap a particular object. *
- * *
- * *
- * *
- * INPUT: ptr to object to zap *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:42PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Set_Target (ObjectClass *target)
- {
- if (Active){
- ZapFrame = 0;
- TargetObject = TARGET_NONE;
- if (target != NULL) TargetObject = target->As_Target();
- LastAttackFrame = Frame;
- TargetDistance = (target != NULL) ? Distance (target->Center_Coord(), Position) : 0;
- }
- }
- /***********************************************************************************************
- * CVC::Attack -- look for objects to attack *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:42PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Attack(void)
- {
- int distance;
- // if(TargetObject) return;
- // if(!TargetObject) return;
- /*
- ** Calculate the position of the center of the vortex.
- */
- int x = Lepton_To_Pixel(Coord_X(Position));
- int y = Lepton_To_Pixel(Coord_Y(Position));
- x += 32;
- y += 12;
- LEPTON lx = Pixel_To_Lepton (x);
- LEPTON ly = Pixel_To_Lepton (y);
- COORDINATE here = XY_Coord (lx, ly);
- /*
- ** Scan through the ground layer objects and see who we should attack
- */
- /*
- ** First scan - find any object directly above the vortex.
- */
- for (int i= 0; i < Map.Layer[LAYER_GROUND].Count(); i++) {
- ObjectClass * obj = Map.Layer[LAYER_GROUND][i];
- if ( obj->Is_Techno() && obj->Strength > 0 ) {
- distance = Distance (obj->Center_Coord(), here);
- if (distance <= CELL_LEPTON_W*2) {
- Set_Target (obj);
- break;
- }
- }
- }
- /*
- ** If we found something to attack then just return
- */
- if (!Target_Legal(TargetObject)) return;
- /*
- ** Scan through all ground level objects.
- **
- ** Objects within range have a chance of being selected based on their distance from the vortex.
- */
- int chance = Random_Pick (0, 1000);
- if (chance > Frame - LastAttackFrame) return;
- for (int i= 0; i < Map.Layer[LAYER_GROUND].Count(); i++) {
- ObjectClass * obj = Map.Layer[LAYER_GROUND][i];
- if ( obj && obj->Is_Techno() ) {
- distance = Distance (obj->Center_Coord(), Position);
- if (distance < CELL_LEPTON_W * Range) {
- chance = Random_Pick (0, distance);
- if (chance < CELL_LEPTON_W) {
- Set_Target (obj);
- break;
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * CVC::Zap_Target -- If the vortex has a target object then zap it with lightning. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:45PM ST : Created *
- *=============================================================================================*/
- #define ZAP_COUNT 1
- void ChronalVortexClass::Zap_Target (void)
- {
- if (!Hidden && Target_Legal(TargetObject) && ZapFrame < ZAP_COUNT) {
- /*
- ** Get the center of the vortex.
- */
- int x = Lepton_To_Pixel(Coord_X(Position));
- int y = Lepton_To_Pixel(Coord_Y(Position));
- x += 32;
- y += 12;
- LEPTON lx = Pixel_To_Lepton (x);
- LEPTON ly = Pixel_To_Lepton (y);
- COORDINATE here = XY_Coord (lx, ly);
- /*
- ** Create a temporary techno object se we can access the lightning ability of the tesla.
- */
- TechnoClass *temptech = new BuildingClass (STRUCT_TESLA, HOUSE_GOOD);
- if (temptech != NULL) {
- temptech->Coord = here;
- ObjectClass * obj = As_Object(TargetObject);
- TARGET target = As_Target (obj->Center_Coord());
- Sound_Effect(VOC_TESLA_ZAP, obj->Center_Coord());
- temptech->Electric_Zap (target, 0, WINDOW_TACTICAL, here, LightningRemap);
- delete temptech;
- /*
- ** Flag the whole map to redraw to cover the lightning.
- */
- Map.Flag_To_Redraw(true);
- /*
- ** Zap the target 3 times but only do damage on the last frame.
- */
- ZapFrame++;
- if (ZapFrame == ZAP_COUNT) {
- ZapFrame = 0;
- int damage = Damage;
- obj->Take_Damage(damage, TargetDistance, WARHEAD_TESLA, NULL, 1);
- TargetObject = TARGET_NONE;
- }
- }
- /*
- ** Vortex might pretend to go away after zapping the target.
- */
- if (Random_Pick (0,2) == 2) Hide();
- }
- }
- /***********************************************************************************************
- * CVC::Coordinate_Remap -- Draws the vortex *
- * *
- * *
- * *
- * INPUT: ptr to view port to draw the vortex into *
- * x offset *
- * y offset *
- * width of vortex *
- * height of vortex *
- * ptr to shading remap tables *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:48PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Coordinate_Remap ( GraphicViewPortClass *inbuffer, int x, int y, int width, int height, unsigned char *remap_table)
- {
- unsigned char getx,gety, remap_color, pixel_color;
- BufferClass destbuf (width * height);
- unsigned char *destptr = (unsigned char*) destbuf.Get_Buffer();
- int destx = x;
- int desty = y;
- int dest_width = width;
- int dest_height = height;
- if (inbuffer->Lock()) {
- /*
- ** Get a pointer to the section of buffer we are going to work on.
- */
- unsigned char *bufptr = (unsigned char *) inbuffer->Get_Offset()
- + destx
- #ifdef WIN32
- + desty* (inbuffer->Get_Width() + inbuffer->Get_XAdd() + inbuffer->Get_Pitch());
- #else
- + desty* (inbuffer->Get_Width() + inbuffer->Get_XAdd());
- #endif
- #ifdef WIN32
- int modulo = inbuffer->Get_Pitch() + inbuffer->Get_XAdd() + inbuffer->Get_Width();
- #else
- int modulo = inbuffer->Get_XAdd() + inbuffer->Get_Width();
- #endif
- for (int yy = desty ; yy < desty+dest_height ; yy++) {
- for (int xx = destx ; xx < destx+dest_width ; xx++) {
- /*
- ** Get the coordinates of the pixel to draw
- */
- getx = *(remap_table++);
- gety = *(remap_table++);
- remap_color = *(remap_table++);
- pixel_color = * (bufptr + getx + (gety * modulo) );
- *(destptr++) = VortexRemapTables [remap_color] [pixel_color];
- }
- remap_table += 3*(width - dest_width);
- destptr += width - dest_width;
- }
- destbuf.To_Page(destx, desty, dest_width, dest_height, *inbuffer);
- inbuffer->Unlock();
- }
- }
- /***********************************************************************************************
- * CVC::Render -- Renders the vortex at its current position. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:49PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Render (void)
- {
- if (Active && !Hidden) {
- char fname [80];
- int frame;
- /*
- ** Calculate which coordinate lookup table we should be using for this frame.
- */
- switch (State) {
- case STATE_GROW:
- frame = 0;
- break;
- case STATE_ROTATE:
- frame = VORTEX_FRAMES;
- break;
- case STATE_SHRINK:
- frame = VORTEX_FRAMES*2;
- break;
- }
- frame += AnimateFrame;
- sprintf (fname, "HOLE%04d.lut", frame);
- void const *lut_ptr = MFCD::Retrieve(fname);
- if (lut_ptr) {
- /*
- ** Build a representation of the area of the screen where the vortex will be
- ** in an off-screen buffer.
- ** This is necessary for clipping as we cant remap pixels from off screen if we build
- ** the image from the hidpage.
- */
- if (!RenderBuffer) {
- RenderBuffer = new GraphicBufferClass(CELL_PIXEL_W * 4, CELL_PIXEL_H * 4, (void*)NULL);
- }
- CELL xc = Coord_XCell (Position);
- CELL yc = Coord_YCell (Position);
- CellClass *cellptr;
- CELL cell;
- TemplateTypeClass const * ttype = 0;
- int icon; // The icon number to use from the template set.
- #ifdef WIN32
- GraphicViewPortClass * oldpage = Set_Logic_Page(RenderBuffer);
- #else
- GraphicBufferClass * oldpage = Set_Logic_Page(RenderBuffer);
- #endif
- /*
- ** Temporarily modify the tactical window so it works with our offscreen buffer
- */
- int wx = WindowList[WINDOW_TACTICAL][WINDOWX];
- int wy = WindowList[WINDOW_TACTICAL][WINDOWY];
- int ww = WindowList[WINDOW_TACTICAL][WINDOWWIDTH];
- int wh = WindowList[WINDOW_TACTICAL][WINDOWHEIGHT];
- WindowList[WINDOW_TACTICAL][WINDOWX] = 0;
- WindowList[WINDOW_TACTICAL][WINDOWY] = 0;
- WindowList[WINDOW_TACTICAL][WINDOWWIDTH] = RenderBuffer->Get_Width();
- WindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = RenderBuffer->Get_Height();
- /*
- ** Loop through all the cells that the vortex overlaps and render the template, smudge
- ** and overlay for each cell.
- */
- for (int y = 0 ; y<4 ; y++) {
- for (int x = 0 ; x<4 ; x++) {
- cell = XY_Cell (xc+x,yc+y);
- if (cell != -1) {
- //cellptr = &Map[ Coord_Whole (Cell_Coord(cell)) ];
- cellptr = &Map [cell];
- /*
- ** Fetch a pointer to the template type associated with this cell.
- */
- if (cellptr->TType != TEMPLATE_NONE && cellptr->TType != TEMPLATE_CLEAR1 && cellptr->TType != 255) {
- ttype = &TemplateTypeClass::As_Reference(cellptr->TType);
- icon = cellptr->TIcon;
- } else {
- ttype = &TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1);
- icon = cellptr->Clear_Icon();
- }
- /*
- ** Draw the template
- */
- if (ttype->Get_Image_Data()) {
- RenderBuffer->Draw_Stamp(ttype->Get_Image_Data(), icon, x*CELL_PIXEL_W, y*CELL_PIXEL_H, NULL, WINDOW_MAIN);
- }
- /*
- ** Draw any smudge.
- */
- if (cellptr->Smudge != SMUDGE_NONE) {
- SmudgeTypeClass::As_Reference(cellptr->Smudge).Draw_It(x*CELL_PIXEL_W, y*CELL_PIXEL_H, cellptr->SmudgeData);
- }
- /*
- ** Draw the overlay object.
- */
- if (cellptr->Overlay != OVERLAY_NONE) {
- OverlayTypeClass const & otype = OverlayTypeClass::As_Reference(cellptr->Overlay);
- IsTheaterShape = (bool)otype.IsTheater; //Tell Build_Frame if this overlay is theater specific
- CC_Draw_Shape(otype.Get_Image_Data(),
- cellptr->OverlayData,
- x*CELL_PIXEL_W + (CELL_PIXEL_W >> 1),
- y*CELL_PIXEL_H + (CELL_PIXEL_H >> 1),
- WINDOW_TACTICAL,
- SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST,
- NULL,
- DisplayClass::UnitShadow);
- IsTheaterShape = false;
- }
- /*
- ** Draw the flag if there is one located at this cell.
- */
- if (cellptr->IsFlagged) {
- void const * flag_remap = HouseClass::As_Pointer(cellptr->Owner)->Remap_Table(false, REMAP_NORMAL);
- CC_Draw_Shape(MFCD::Retrieve("FLAGFLY.SHP"), Frame % 14, x+(ICON_PIXEL_W/2), y+(ICON_PIXEL_H/2), WINDOW_TACTICAL, SHAPE_CENTER|SHAPE_GHOST|SHAPE_FADING, flag_remap, DisplayClass::UnitShadow);
- }
- }
- }
- }
- Set_Logic_Page(oldpage);
- /*
- ** Restore the tactical window to its correct value
- */
- WindowList[WINDOW_TACTICAL][WINDOWX] = wx;
- WindowList[WINDOW_TACTICAL][WINDOWY] = wy;
- WindowList[WINDOW_TACTICAL][WINDOWWIDTH] = ww;
- WindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = wh;
- /*
- ** Render the vortex over the cells we just rendered to our buffer
- */
- Coordinate_Remap (RenderBuffer, Lepton_To_Pixel(Coord_X(Coord_Fraction(Position))),
- Lepton_To_Pixel(Coord_Y(Coord_Fraction(Position))),
- 64,
- 64,
- (unsigned char*) lut_ptr);
- /*
- ** Calculate the pixel position of our fresh block of cells on the tactical map so
- ** we can blit it to the hid page.
- */
- COORDINATE render_pos = XY_Coord(xc * CELL_LEPTON_W, yc * CELL_LEPTON_H); //Coord_Whole(Position);
- int x, y;
- Map.Coord_To_Pixel(render_pos, x, y);
- /*
- ** Create a view port to blit to
- */
- GraphicViewPortClass target (LogicPage->Get_Graphic_Buffer(),
- 0,
- LogicPage->Get_YPos(),
- Lepton_To_Pixel (Map.TacLeptonWidth),
- Lepton_To_Pixel (Map.TacLeptonHeight));
- /*
- ** Do some clipping since the library clipping gets it wrong.
- */
- int diff;
- int source_x = 0;
- int source_y = 0;
- int source_width = CELL_PIXEL_W*4;
- int source_height = CELL_PIXEL_H*4;
- int dest_x = x;
- int dest_y = y;
- int dest_width = source_width;
- int dest_height = source_height;
- if (dest_x < 0) {
- source_width += dest_x;
- dest_width += dest_x;
- source_x -= dest_x;
- dest_x = 0;
- }
- if (dest_y <0) {
- source_height += dest_y;
- dest_height += dest_y;
- source_y -= dest_y;
- dest_y = 0;
- }
- if (dest_x + dest_width > target.Get_Width() ) {
- diff = dest_x + dest_width - target.Get_Width();
- dest_width -= diff;
- source_width -= diff;
- }
- if (dest_y + dest_height > target.Get_Height() ) {
- diff = dest_y + dest_height - target.Get_Height();
- dest_height -= diff;
- source_height -= diff;
- }
- /*
- ** Blit our freshly draw cells and vortex into their correct position on the hidpage
- */
- if (dest_width > 0 && dest_height > 0) {
- RenderBuffer->Blit (target, source_x, source_y, dest_x, dest_y, dest_width, dest_height, false);
- }
- }
- }
- }
- /***********************************************************************************************
- * CVC::Set_Redraw -- Flags the cells under to vortex to redraw. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:50PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Set_Redraw(void)
- {
- if (Active) {
- CELL xc = Coord_XCell (Position);
- CELL yc = Coord_YCell (Position);
- CELL cell;
- for (int y = MAX(0,yc - 1) ; y< yc+4 ; y++) {
- for (int x = MAX(0, xc-1) ; x< xc + 4 ; x++) {
- cell = XY_Cell (x,y);
- if (cell != -1) {
- Map[cell].Redraw_Objects();
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * CVC::Setup_Remap_Tables -- Initialises the color remap tables based on theater. *
- * *
- * *
- * *
- * INPUT: Theater *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/29/96 4:51PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Setup_Remap_Tables (TheaterType theater)
- {
- /*
- ** The names of the remap files for each theater
- */
- static char _remaps[3][13] ={
- "TEMP_VTX.PAL",
- "SNOW_VTX.PAL",
- "INTR_VTX.PAL"
- };
- int i;
- /*
- ** If the theater has changed then load the remap tables from disk if they exist or create
- ** them if they dont.
- */
- if (theater != Theater) {
- Theater = theater;
- CCFileClass file (_remaps[(int)Theater]);
- if (file.Is_Available()) {
- file.Read (VortexRemapTables, MAX_REMAP_SHADES*256);
- } else {
- for (i=0 ; i<MAX_REMAP_SHADES ; i++) {
- Build_Fading_Table ( GamePalette, &VortexRemapTables[i][0], 0, 240- ((i*256)/MAX_REMAP_SHADES) );
- }
- file.Write (VortexRemapTables, MAX_REMAP_SHADES*256);
- }
- }
- /*
- ** Set up the remap table for the lightning
- */
- for (i=0 ; i<256 ; i++) {
- LightningRemap[i] = i;
- }
- LightningRemap[192] = 208;
- LightningRemap[193] = 209;
- LightningRemap[194] = 210;
- LightningRemap[195] = 211;
- LightningRemap[196] = 212;
- LightningRemap[197] = 213;
- LightningRemap[198] = 214;
- LightningRemap[199] = 215;
- }
- /***********************************************************************************************
- * CVC::Build_Fading_Table -- Builds a fading color lookup table. *
- * *
- * *
- * *
- * INPUT: ptr to palette to base tables on *
- * ptr to buffer to put clut in. *
- * color to bias colors to *
- * percentage of bias *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: Based on Conquer_Build_Fading_Table *
- * *
- * HISTORY: *
- * 8/29/96 4:53PM ST : Created *
- *=============================================================================================*/
- void ChronalVortexClass::Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)
- {
- if (dest) {
- unsigned char * ptr = (unsigned char *)dest;
- /*
- ** Find an appropriate remap color index for every color in the palette.
- ** There are certain exceptions to this, but they are trapped within the
- ** loop.
- */
- for (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {
- /*
- ** If this color should not be remapped, then it will be stored as a remap
- ** to itself. This is effectively no remap.
- */
- if (index == 0 ||
- (index >= CYCLE_COLOR_START && index < (CYCLE_COLOR_START + CYCLE_COLOR_COUNT)) ||
- index == CC_PULSE_COLOR ||
- index == CC_EMBER_COLOR) {
- *ptr++ = index;
- } else {
- /*
- ** Find the color that, ideally, the working color should be remapped
- ** to in the special remap range.
- */
- RGBClass trycolor = palette[index];
- trycolor.Adjust(frac, palette[color]); // Try to match this color.
- /*
- ** Search through the remap range to find the color that should be remapped
- ** to.
- */
- int best = -1;
- int bvalue = 0;
- for (int id = 0; id < PaletteClass::COLOR_COUNT; id++) {
- if (id != 0 &&
- (id < CYCLE_COLOR_START || id >= (CYCLE_COLOR_START + CYCLE_COLOR_COUNT)) &&
- id != CC_PULSE_COLOR &&
- id != CC_EMBER_COLOR) {
- int diff = palette[id].Difference(trycolor);
- if (best == -1 || diff < bvalue) {
- best = id;
- bvalue = diff;
- }
- }
- }
- *ptr++ = best;
- }
- }
- }
- }
- void ChronalVortexClass::Detach(TARGET target)
- {
- if (Target_Legal(target) && target == TargetObject) {
- Set_Target(NULL);
- }
- }
|