From a405ebc85165a5315885e0c4d0a2748b28c09b08 Mon Sep 17 00:00:00 2001 From: n0body <> Date: Fri, 11 Jul 2003 13:21:17 +0000 Subject: [PATCH] CVS test --- src/unit/unit.cpp | 377 +++++++++++++++++----------------------------- 1 file changed, 135 insertions(+), 242 deletions(-) diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index 61bd65c2b..9e2216776 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -1,7 +1,7 @@ // _________ __ __ // / _____// |_____________ _/ |______ ____ __ __ ______ // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ -// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ \ +// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > // \/ \/ \//_____/ \/ // ______________________ ______________________ @@ -80,7 +80,7 @@ global Unit* DestroyedBuildings; /// List of DestroyedBuildings global Unit* CorpseList; /// List of Corpses On Map global int HitPointRegeneration; /// Hit point regeneration for all units -global int XpDamage; /// Hit point regeneration for all units +global int XpDamage; /// Hit point regeneration for all units global char EnableTrainingQueue; /// Config: training queues enabled global char EnableBuildingCapture; /// Config: capture buildings enabled global char RevealAttacker; /// Config: reveal attacker enabled @@ -411,7 +411,7 @@ global void AssignUnitToPlayer(Unit *unit, Player *player) unit->Player=player; unit->Stats=&type->Stats[unit->Player->Player]; - unit->Colors=player->UnitColors; + unit->Colors=&player->UnitColors; } /** @@ -543,12 +543,14 @@ global void PlaceUnit(Unit* unit,int x,int y) // // Update fog of war, if unit belongs to player on this computer // - if( unit->Next && unit->Removed ) { - MapUnmarkSight(unit->Player,unit->Next->X+unit->Next->Type->TileWidth/2 - ,unit->Next->Y+unit->Next->Type->TileHeight/2 + if( unit->Container && unit->Removed ) { + MapUnmarkSight(unit->Player,unit->Container->X+unit->Container->Type->TileWidth/2 + ,unit->Container->Y+unit->Container->Type->TileHeight/2 ,unit->CurrentSightRange); } - unit->Next = NULL; + if (unit->Container) { + RemoveUnitFromContainer(unit); + } unit->CurrentSightRange=unit->Stats->SightRange; MapMarkSight(unit->Player,x,y,unit->CurrentSightRange); @@ -611,7 +613,61 @@ global Unit* MakeUnitAndPlace(int x,int y,UnitType* type,Player* player) return unit; } -/** +/* +** Add unit to a container. It only updates linked list stuff +** +** @param unit Pointer to unit. +** @param host Pointer to container. +*/ +global void AddUnitInContainer(Unit* unit, Unit* host) +{ + if (unit->Container) { + printf("Unit is already contained.\n"); + exit(0); + } + unit->Container=host; + if (host->InsideCount==0) { + unit->NextContained=unit->PrevContained=unit; + } else { + unit->NextContained=host->UnitInside; + unit->PrevContained=host->UnitInside->PrevContained; + host->UnitInside->PrevContained->NextContained=unit; + host->UnitInside->PrevContained=unit; + } + host->UnitInside=unit; + ++host->InsideCount; +} + +/* +** Remove unit from a container. It only updates linked list stuff +** +** @param unit Pointer to unit. +*/ +global void RemoveUnitFromContainer(Unit* unit) +{ + Unit* host; + host=unit->Container; + if (!unit->Container) { + printf("Unit not contained.\n"); + exit(0); + } + if (host->InsideCount==0) { + printf("host's inside count reached -1."); + exit(0); + } + host->InsideCount--; + unit->NextContained->PrevContained=unit->PrevContained; + unit->PrevContained->NextContained=unit->NextContained; + if (host->InsideCount==0) { + host->UnitInside=NoUnitP; + } else { + if (host->UnitInside==unit) + host->UnitInside=unit->NextContained; + } + unit->Container=NoUnitP; +} + +/* ** Remove unit from map. ** ** Update selection. @@ -628,9 +684,9 @@ global void RemoveUnit(Unit* unit, Unit* host) const UnitType* type; unsigned flags; - if( unit->Removed && unit->Next ) { - MapUnmarkSight(unit->Player,unit->Next->X+unit->Next->Type->TileWidth/2 - ,unit->Next->Y+unit->Next->Type->TileHeight/2 + if( unit->Removed && unit->Container ) { + MapUnmarkSight(unit->Player,unit->Container->X+unit->Container->Type->TileWidth/2 + ,unit->Container->Y+unit->Container->Type->TileHeight/2 ,unit->CurrentSightRange); } else { MapUnmarkSight(unit->Player,unit->X+unit->Type->TileWidth/2 @@ -642,11 +698,11 @@ global void RemoveUnit(Unit* unit, Unit* host) MapMarkSight(unit->Player,host->X+host->Type->TileWidth/2, host->Y+host->Type->TileWidth/2, unit->CurrentSightRange); + AddUnitInContainer(unit,host); } if( unit->Removed ) { // could happen! // If unit is removed (inside) and building is destroyed. - unit->Next=NULL; return; } unit->Removed=1; @@ -1722,6 +1778,7 @@ global void UnitIncrementHealth(void) global void ChangeUnitOwner(Unit* unit,Player* newplayer) { int i; + Unit* uins; Player* oldplayer; oldplayer=unit->Player; @@ -1732,25 +1789,15 @@ global void ChangeUnitOwner(Unit* unit,Player* newplayer) return; } - // For st*rcr*ft (dark archons), - if( unit->Type->Transporter ) { - for( i=0; i<MAX_UNITS_ONBOARD; i++) { - if( unit->OnBoard[i] ) { - ChangeUnitOwner(unit->OnBoard[i],newplayer); - } - } - } - // FIXME: should use a better methode, linking all units in a building - // FIXME: f.e. with the next pointer. How??? // - // Rescue all units in buildings + // Rescue all units in buildings/transporters. // printf("Rescue of a %s at 0x%X\n",unit->Type->Name,(unsigned)unit); - for( i=0; i<NumUnits; i++ ) { - if( Units[i]->Removed && Units[i]->Next==unit ) { - printf("Chain rescue of a %s\n at 0x%X",Units[i]->Type->Name,(unsigned)Units[i]); - ChangeUnitOwner(Units[i],newplayer); - } + + uins=unit->UnitInside; + for( i=unit->InsideCount; i; --i,uins=uins->NextContained) { + printf("Chain rescue of a %s\n at 0x%X",Units[i]->Type->Name,(unsigned)Units[i]); + ChangeUnitOwner(uins,newplayer); } // @@ -1794,12 +1841,12 @@ global void ChangeUnitOwner(Unit* unit,Player* newplayer) unit->Player=newplayer; - if ( unit->Removed&&unit->Next ) { - MapUnmarkSight(oldplayer,unit->Next->X+unit->Next->Type->TileWidth/2 - ,unit->Next->Y+unit->Next->Type->TileHeight/2 + if ( unit->Removed && unit->Container ) { + MapUnmarkSight(oldplayer,unit->Container->X+unit->Container->Type->TileWidth/2 + ,unit->Container->Y+unit->Container->Type->TileHeight/2 ,unit->CurrentSightRange); - MapMarkSight(unit->Player,unit->Next->X+unit->Next->Type->TileWidth/2 - ,unit->Next->Y+unit->Next->Type->TileHeight/2 + MapMarkSight(unit->Player,unit->Container->X+unit->Container->Type->TileWidth/2 + ,unit->Container->Y+unit->Container->Type->TileHeight/2 ,unit->CurrentSightRange); } else { MapUnmarkSight(oldplayer,unit->X+unit->Type->TileWidth/2 @@ -1854,7 +1901,6 @@ local void ChangePlayerOwner(Player* oldplayer,Player* newplayer) } ChangeUnitOwner(unit,newplayer); unit->Blink=5; - unit->Rescued=1; unit->RescuedFrom=oldplayer; } } @@ -1932,15 +1978,14 @@ global void RescueUnits(void) // // City center converts complete race // NOTE: I use a trick here, centers could - // store gold. - if( unit->Type->StoresGold ) { + // store gold. FIXME!!! + if( unit->Type->Stores[GoldCost] ) { ChangePlayerOwner(p,around[i]->Player); break; } unit->RescuedFrom=unit->Player; ChangeUnitOwner(unit,around[i]->Player); unit->Blink=5; - unit->Rescued=1; PlayGameSound(GameSounds.Rescue[unit->Player->Race].Sound ,MaxSampleVolume); break; @@ -2070,16 +2115,16 @@ global void DropOutOnSide(Unit* unit,int heading,int addx,int addy) //DebugCheck( !unit->Removed ); // FIXME: better and quicker solution, to find the building. - x=y=-1; - if( unit->Next ) { - x=unit->Next->X; - y=unit->Next->Y; + if( unit->Container ) { + x=unit->Container->X; + y=unit->Container->Y; } else { x=unit->X; y=unit->Y; - DebugLevel0Fn("No building?\n"); + // n0b0dy: yes, when training an unit. } + mask=UnitMovementMask(unit); if( heading<LookingNE || heading>LookingNW) { @@ -2182,11 +2227,10 @@ global void DropOutNearest(Unit* unit,int gx,int gy,int addx,int addy) // FIXME: better and quicker solution, to find the building. x=y=-1; - if( unit->Next ) { - x=unit->Next->X; - y=unit->Next->Y; + if( unit->Container ) { + x=unit->Container->X; + y=unit->Container->Y; } else { - DebugLevel0Fn("No building?\n"); x=unit->X; y=unit->Y; } @@ -2263,26 +2307,17 @@ global void DropOutNearest(Unit* unit,int gx,int gy,int addx,int addy) */ global void DropOutAll(const Unit* source) { - // FIXME: Rewrite this use source->Next; - // FIXME: above is wrong, NEW_FOW use Next in another way. - // FIXME: (mr-russ) can't use source->Next, it's on map, and Next - // points to next unit on tile. - Unit** table; Unit* unit; int i; - i=0; - for( table=Units; table<Units+NumUnits; table++ ) { - unit=*table; - if( unit->Removed && unit->Next==source ) { - ++i; - DropOutOnSide(unit,LookingW + unit=source->UnitInside; + for( i=source->InsideCount; i; --i,unit=unit->NextContained ) { + DropOutOnSide(unit,LookingW ,source->Type->TileWidth,source->Type->TileHeight); - DebugCheck( unit->Orders[0].Goal ); - unit->Orders[0].Action=UnitActionStill; - unit->Wait=unit->Reset=1; - unit->SubAction=0; - } + DebugCheck( unit->Orders[0].Goal ); + unit->Orders[0].Action=UnitActionStill; + unit->Wait=unit->Reset=1; + unit->SubAction=0; } DebugLevel0Fn("Drop out %d of %d\n" _C_ i _C_ source->Data.Resource.Active); } @@ -2343,7 +2378,7 @@ global int CanBuildHere(const UnitType* type,int x,int y) } } - if( type->StoresGold ) { + if( type->Stores[GoldCost] ) { // // Gold deposit can't be build too near to gold-mine. // @@ -2392,7 +2427,7 @@ global int CanBuildHere(const UnitType* type,int x,int y) } next: - if( type->StoresOil ) { + if( type->Stores[OilCost] ) { // // Oil deposit can't be build too near to oil-patch or platform. // @@ -2630,7 +2665,7 @@ global Unit* FindGoldMine(const Unit* unit,int x,int y) // // Find the nearest gold depot // - if( (destu=FindGoldDeposit(unit,x,y)) ) { + if( (destu=FindDeposit(unit->Player,x,y,GoldCost)) ) { NearestOfUnit(destu,x,y,&destx,&desty); } bestd=99999; @@ -2765,100 +2800,6 @@ global Unit* FindGoldMine(const Unit* unit,int x,int y) return NoUnitP; } -/** -** Find gold deposit (where we can deliver gold). -** -** @param source Pointer for source unit. -** @param x X tile position to start. -** @param y Y tile position to start. -** -** @return Pointer to the nearest gold depot. -*/ -global Unit* FindGoldDeposit(const Unit* source,int x,int y) -{ - Unit** table; - Unit* unit; - Unit* best; - int best_d; - int d; - const Player* player; - - // FIXME: this is not the best one - // We need the deposit with the shortest way! - // At least it must be reachable! - // Should use the same pathfinder flood fill, like the attacking - // code. - player=source->Player; - - best=NoUnitP; - best_d=99999; - for( table=player->Units; table<player->Units+player->TotalNumUnits; - table++ ) { - unit=*table; - // Want gold deposit and not dieing. - if( !unit->Type->StoresGold || UnitUnusable(unit) ) { - continue; - } - d=MapDistanceToUnit(x,y,unit); - // FIXME: UnitReachable didn't work with unit inside - if( d<best_d /* && (d=UnitReachable(source,unit,1)) && d<best_d */ ) { - best_d=d; - best=unit; - } - } - DebugLevel3Fn("%d %d,%d\n" _C_ best?UnitNumber(best):-1 _C_ - best?best->X:-1 _C_ best?best->Y:-1); - return best; -} - -/** -** Find wood deposit. -** -** @param player A deposit owning this player -** @param x X tile position to start. -** @param y Y tile position to start. -** -** @return Pointer to the nearest wood depot. -*/ -global Unit* FindWoodDeposit(const Player* player,int x,int y) -{ - Unit* unit; - Unit* best; - Unit** units; - int nunits; - int best_d; - int d,i; - - // FIXME: this is not the best one - // We need the deposit with the shortest way! - // At least it must be reachable! - // FIXME: Could we use unit-cache to find it faster? - // - - best=NoUnitP; - best_d=99999; - nunits=player->TotalNumUnits; - units=player->Units; - for( i=0; i<nunits; i++ ) { - unit=units[i]; - if( UnitUnusable(unit) ) { - continue; - } - // Want wood-deposit - if( unit->Type->StoresWood || unit->Type->StoresGold ) { - d=MapDistanceToUnit(x,y,unit); - if( d<best_d ) { - best_d=d; - best=unit; - } - } - } - - DebugLevel3Fn("%d %d,%d\n" _C_ best?UnitNumber(best):-1 _C_ - best?best->X:-1 _C_ best?best->Y:-1); - return best; -} - #if 0 /** ** Find wood in sight range. @@ -3017,7 +2958,7 @@ global int FindWoodInSight(const Unit* unit,int* px,int* py) // // Find the nearest wood depot // - if( (destu=FindWoodDeposit(unit->Player,x,y)) ) { + if( (destu=FindDeposit(unit->Player,x,y,WoodCost)) ) { NearestOfUnit(destu,x,y,&destx,&desty); } bestd=99999; @@ -3210,15 +3151,16 @@ global Unit* FindOilPlatform(const Player* player,int x,int y) } /** -** Find oil deposit. +** Find deposit. This will find a deposit for a resource ** -** @param source A deposit for this unit. +** @param player The player the deposit must belong to. ** @param x Nearest to X position. ** @param y Nearest to Y position. +** @param resource The resource oyu need the deposit to hold. ** ** @return NoUnitP or oil deposit unit */ -global Unit* FindOilDeposit(const Unit* source,int x,int y) +global Unit* FindDeposit(const Player* player,int x,int y,int resource) { Unit* unit; Unit* best; @@ -3226,14 +3168,12 @@ global Unit* FindOilDeposit(const Unit* source,int x,int y) int nunits; int best_d; int d,i; - const Player* player; // FIXME: this is not the best one // We need the deposit with the shortest way! // At least it must be reachable! // FIXME: Could we use unit-cache to find it faster? // - player=source->Player; best=NoUnitP; best_d=INT_MAX; @@ -3244,8 +3184,7 @@ global Unit* FindOilDeposit(const Unit* source,int x,int y) if( UnitUnusable(unit) ) { continue; } - // Want oil-deposit - if( unit->Type->StoresOil ) { + if( unit->Type->Stores[resource] ) { d=MapDistanceToUnit(x,y,unit); if( d<best_d // FIXME: UnitReachable didn't work with unit inside @@ -3451,20 +3390,15 @@ global void LetUnitDie(Unit* unit) // // Building with units inside? // - if( type->GoldMine - || type->StoresGold || type->StoresWood - || type->GivesOil || type->StoresOil - || unit->Orders[0].Action==UnitActionBuilded ) { - // - // During oil platform build, the worker holds the oil value, - // but if canceling building the platform, the worker is already - // outside. - if( type->GivesOil - && unit->Orders[0].Action==UnitActionBuilded - && unit->Data.Builded.Worker ) { - // Restore value for oil-patch - unit->Value=unit->Data.Builded.Worker->Value; - } + // + // During oil platform build, the worker holds the oil value, + // but if canceling building the platform, the worker is already + // outside. + if( type->GivesOil + && unit->Orders[0].Action==UnitActionBuilded + && unit->Data.Builded.Worker ) { + // Restore value for oil-patch + unit->Value=unit->Data.Builded.Worker->Value; } DestroyAllInside(unit); @@ -3556,56 +3490,17 @@ global void LetUnitDie(Unit* unit) global void DestroyAllInside(Unit* source) { Unit* unit; - Unit* table[UnitMax]; int i; - int j; - // - // Destroy all units in Transporters - // - if( source->Type->Transporter ) { - for( i=0; i<MAX_UNITS_ONBOARD; i++) { - // FIXME: check if valid pointer - if( (unit=source->OnBoard[i]) ) { - // FIXME: no corpse! - // LetUnitDie(unit); - RemoveUnit(unit,NULL); - UnitLost(unit); - UnitClearOrders(unit); - ReleaseUnit(unit); - } - } - return; - } - - // - // Destroy the peon in building under construction... - // - if( source->Orders[0].Action==UnitActionBuilded - && source->Data.Builded.Worker ) { - LetUnitDie(source->Data.Builded.Worker); - return; - } - - // FIXME: should use a better methode, linking all units in a building - // FIXME: f.e. with the next pointer. - // - // Destroy all units in buildings or Resources (mines...) - // - j = 0; - for( i=0; i<NumUnits; i++ ) { - unit=Units[i]; - if( unit->Removed && unit->Next==source ) { - table[j++] = unit; - } - } - for( i=0; i<j; i++ ) { - unit=table[i]; - RemoveUnit(unit,NULL); - UnitLost(unit); - UnitClearOrders(unit); + // FIXME: n0b0dy: No corpses, is that corrent behaviour? + unit=source->UnitInside; + for( i=source->InsideCount; i; --i,unit=unit->NextContained ) { + RemoveUnit(unit,NULL); + UnitLost(unit); + UnitClearOrders(unit); ReleaseUnit(unit); } + } @@ -4198,6 +4093,7 @@ local void SaveOrder(const Order* order,FILE* file) global void SaveUnit(const Unit* unit,FILE* file) { char* ref; + Unit* uins; int i; fprintf(file,"\n(unit %d ",UnitNumber(unit)); @@ -4214,7 +4110,7 @@ global void SaveUnit(const Unit* unit,FILE* file) fprintf(file,"'name \"%s\" ",unit->Name); } - if( unit->Next && unit->Removed ) { + if( unit->Next ) { fprintf(file,"'next '%d ",UnitNumber(unit->Next)); } @@ -4263,14 +4159,14 @@ global void SaveUnit(const Unit* unit,FILE* file) if( unit->Selected ) { fprintf(file," 'selected"); } - if( unit->Rescued ) { - fprintf(file," 'rescued"); + if( unit->RescuedFrom ) { fprintf(file," 'rescued-from %d",unit->RescuedFrom->Player); } - if( unit->Next && unit->Removed ) { + // n0b0dy: How is this usefull? + if( unit->Container && unit->Removed ) { fprintf(file," 'host-tile '(%d %d) ", - unit->Next->X+unit->Next->Type->TileWidth/2, - unit->Next->Y+unit->Next->Type->TileHeight/2); + unit->Container->X+unit->Container->Type->TileWidth/2, + unit->Container->Y+unit->Container->Type->TileHeight/2); } fprintf(file," 'visible \""); for( i=0; i<PlayerMax; ++i ) { @@ -4319,15 +4215,12 @@ global void SaveUnit(const Unit* unit,FILE* file) if( unit->Revealer ) { fprintf(file," 'revealer"); } - fprintf(file,"\n 'on-board #("); - for( i=0; i<MAX_UNITS_ONBOARD; ++i ) { - if( unit->OnBoard[i] ) { - fprintf(file,"%s",ref=UnitReference(unit->OnBoard[i])); - free(ref); - } else { - fprintf(file,"()"); - } - if( i<MAX_UNITS_ONBOARD-1 ) { + fprintf(file," 'units-contained-count %d",unit->InsideCount); + fprintf(file,"\n 'units-contained #("); + uins=unit->UnitInside; + for( i=unit->InsideCount; i; --i,uins=uins->NextContained ) { + fprintf(file,"%s",ref=UnitReference(uins)); + if( i>1 ) { fputc(' ',file); } }