From 946290f82374d60570665b5ef25a31f3189238ea Mon Sep 17 00:00:00 2001 From: n0body <> Date: Thu, 21 Aug 2003 06:12:04 +0000 Subject: [PATCH] Show entire path while pressing shift. Tweak code in mouse.c(better when clicking on a moving unit). Adding building methods. Other minor tweaks. --- doc/ChangeLog.html | 31 ++-- src/action/action_attack.cpp | 18 +- src/action/action_board.cpp | 2 + src/action/action_build.cpp | 154 ++++++++++------- src/action/action_follow.cpp | 33 +++- src/action/action_move.cpp | 3 +- src/action/action_resource.cpp | 13 +- src/action/action_still.cpp | 21 +-- src/action/actions.cpp | 4 +- src/action/command.cpp | 6 + src/include/iolib.h | 6 +- src/include/unit.h | 24 +-- src/include/unittype.h | 3 + src/sound/flac.cpp | 4 +- src/ui/mainscr.cpp | 7 +- src/ui/mouse.cpp | 268 +++++++++++++----------------- src/unit/script_unittype.cpp | 7 + src/unit/unit_draw.cpp | 290 ++++++++++++++------------------- src/unit/unit_find.cpp | 2 + src/unit/unittype.cpp | 14 +- 20 files changed, 445 insertions(+), 465 deletions(-) diff --git a/doc/ChangeLog.html b/doc/ChangeLog.html index 562901de2..3926a2799 100644 --- a/doc/ChangeLog.html +++ b/doc/ChangeLog.html @@ -36,16 +36,17 @@ <li>Future 1.19 Release<p> <ul> <li>++ - <li>You can now save in gz format (from Russel Smith and Crestez Leonard). - <li>Fixed drawing order for units on the same level (from Russel Smith). + <li>Added flags for different building methods (from Crestez Leonard). + <li>Pressing shift will now show all waypoints, including building outlines (from Crestez Leonard) + <li>You can now save in gz format (from Russell Smith and Crestez Leonard). + <li>Fixed drawing order for units on the same level (from Russell Smith). <li>Remove *ScreenMapPositon bloat (from Crestez Leonard). <li>Fixed MacOS X compilation problems (from Duncan McQueen). <li>Fixed middle-mouse scrolling, speed now configurable (from Martin Renold). - <li>Removed global unit types for tankers, generalized gold mining (from Crestez Dan Leonard). - <li>Removed unit-attack-peon and unit-attack-peasant (from Crestez Dan Leonard). + <li>Removed global unit types for tankers, generalized gold mining (from Crestez Leonard). + <li>Removed unit-attack-peon and unit-attack-peasant (from Crestez Leonard). <li>Fixed minor mac compilation bug (from zratchet). <li>Fixed small bugs from NEW_UI (from Martin Renold). - <li>A lot of progress in resource configurability (from Crestez Dan Leonard). <li>Minimap panel can have its own palette now (from Martin Renold). <li>NEW_UI: Dropped of displaying the current unit action with the buttons (from Martin Renold). <li>NEW_UI: Dropped Alt-Buttons support (did anybody use this?) (from Martin Renold). @@ -54,21 +55,21 @@ <li>Added guile support as an alternative scheme interpretor (Fron Ingo Ruhnke). <li>Fixed loading games saved with different resolutions (from Martin Renold). <li>Removed spaces from data files (from Martin Renold). - <li>Changed the handling of contained units to a circular linked list (from Crestez Dan Leonard). - <li>Compacted Unit::Rescued and Unit::Rescued from (from Crestez Dan Leonard). - <li>Change Unit::Colors to a pointer(saves memory) (from Crestez Dan Leonard). + <li>Changed the handling of contained units to a circular linked list (from Crestez Leonard). + <li>Compacted Unit::Rescued and Unit::Rescued from (from Crestez Leonard). + <li>Change Unit::Colors to a pointer(saves memory) (from Crestez Leonard). <li>Renamed project to Stratagus and fixed most internal references to the Freecraft name (From Ingo Ruhnke). </ul> <p><li>Freecraft renamed to Stratagus.<p> <ul> - <li>You can select two units on different land masses and they will both board (from Crestez Dan Leonard). - <li>Set Harvest with right-click from a building (from Crestez Dan Leonard). - <li>Fixed bug where transporter and unit follow each other (from Crestez Dan Leonard). - <li>Transporter will find another place to unload if it didn't unload completely (from Crestez Dan Leonard). - <li>Fixed bug #700283: Rescued Units don't retain their color after save/load (from Crestez Dan Leonard). + <li>You can select two units on different land masses and they will both board (from Crestez Leonard). + <li>Set Harvest with right-click from a building (from Crestez Leonard). + <li>Fixed bug where transporter and unit follow each other (from Crestez Leonard). + <li>Transporter will find another place to unload if it didn't unload completely (from Crestez Leonard). + <li>Fixed bug #700283: Rescued Units don't retain their color after save/load (from Crestez Leonard). <li>Fixed bug #743369:'Raise Dead' spell bug (from Russell Smith). <li>Fixed bug #747212: segfault on loading (from Russell Smith). - <li>Fixed bug where rescued flag wasn't saved (from Crestez Dan Leonard). + <li>Fixed bug where rescued flag wasn't saved (from Crestez Leonard). <li>Fixed bug #206908: A* bug. (from Russell Smith). <li>A* turned on, More realistic pathfinding allowed (from Russell Smith). <li>Adjustment of pathfinders to give better performance (from Russell Smith). @@ -109,7 +110,7 @@ <ul> <li>+++ <li>Fixed bug #749944: UI clipping problems on right panel (from Jimmy Salmon). - <li>Fixed bug where rescued flag wasn't saved (from Crestez Dan Leonard). + <li>Fixed bug where rescued flag wasn't saved (from Crestez Leonard). <li>Fixed bug #697744: cannot cancel patrol when mixed units selected (from Jimmy Salmon). <li>Fixed bug #703143: Can't give orders to units (from Russell Smith). <li>Fixed bug #697741: tileset not drawn when loading saved game (from Jimmy Salmon). diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp index 3b1bb745a..8f4874c99 100644 --- a/src/action/action_attack.cpp +++ b/src/action/action_attack.cpp @@ -353,15 +353,17 @@ local void MoveToTarget(Unit* unit) unit->State=unit->SubAction=0; // Return to old task? if( err==PF_UNREACHABLE ) { - DebugLevel0Fn("Target not reachable, unit: %d" _C_ UnitNumber(unit)); + DebugLevel3Fn("Target not reachable, unit: %d" _C_ UnitNumber(unit)); if( goal ) { - DebugLevel0(", target %d\n" _C_ UnitNumber(goal)); + DebugLevel3(", target %d range %d\n" _C_ UnitNumber(goal) _C_ unit->Orders[0].RangeX); } else { - DebugLevel0(", (%d,%d) Tring with more range...\n" _C_ unit->Orders[0].X _C_ unit->Orders[0].Y); + DebugLevel3(", (%d,%d) Tring with more range...\n" _C_ unit->Orders[0].X _C_ unit->Orders[0].Y); } if( unit->Orders[0].RangeX < TheMap.Width || unit->Orders[0].RangeY < TheMap.Height ) { - // Try again with more range + // Try again later and with a bigger range. + // FIXME: does the range ever decrease? + unit->Wait=10; unit->Orders[0].RangeX++; unit->Orders[0].RangeY++; return; @@ -605,16 +607,16 @@ global void HandleActionAttack(Unit* unit) // // Move near to the target. // - case 4: - case 4+WEAK_TARGET: + case MOVE_TO_TARGET: + case MOVE_TO_TARGET+WEAK_TARGET: MoveToTarget(unit); break; // // Attack the target. // - case 5: - case 5+WEAK_TARGET: + case ATTACK_TARGET: + case ATTACK_TARGET+WEAK_TARGET: AttackTarget(unit); break; diff --git a/src/action/action_board.cpp b/src/action/action_board.cpp index 195d8553a..35b8faa7d 100644 --- a/src/action/action_board.cpp +++ b/src/action/action_board.cpp @@ -66,6 +66,8 @@ local int MoveToTransporter(Unit* unit) i=DoActionMove(unit); // We have to reset a lot, or else they will circle each other and stuff. if (x!=unit->X||y!=unit->Y) { + unit->Orders[0].RangeX=1; + unit->Orders[0].RangeY=1; NewResetPath(unit); } // New code has this as default. diff --git a/src/action/action_build.cpp b/src/action/action_build.cpp index 171b2d31e..4a9864353 100644 --- a/src/action/action_build.cpp +++ b/src/action/action_build.cpp @@ -151,9 +151,9 @@ global void HandleActionBuild(Unit* unit) // Some tries to build the building. // if( unit->SubAction++<10 ) { - // To keep the load low, retry each 1/4 second. + // To keep the load low, retry each 10 cycles // NOTE: we can already inform the AI about this problem? - unit->Wait=CYCLES_PER_SECOND/4+unit->SubAction; + unit->Wait=10; return; } @@ -256,6 +256,7 @@ global void HandleActionBuild(Unit* unit) build->Orders[0].Action=UnitActionBuilded; build->Data.Builded.Sum=0; // FIXME: Is it necessary? + build->Data.Builded.Cancel=0; // FIXME: Is it necessary? build->Data.Builded.Val=stats->HitPoints; n=(stats->Costs[TimeCost]*CYCLES_PER_SECOND/6)/(SpeedBuild*5); if( n ) { @@ -266,22 +267,37 @@ global void HandleActionBuild(Unit* unit) DebugCheck( build->Data.Builded.Add!=stats->HitPoints ); } build->Data.Builded.Sub=n; - build->Data.Builded.Cancel=0; // FIXME: Is it necessary? - build->Data.Builded.Worker=unit; - DebugLevel3Fn("Build Sum %d, Add %d, Val %d, Sub %d\n" - _C_ build->Data.Builded.Sum _C_ build->Data.Builded.Add - _C_ build->Data.Builded.Val _C_ build->Data.Builded.Sub); build->Wait=CYCLES_PER_SECOND/6; UpdateConstructionFrame(build); - unit->Value=build->Value; // worker holding value while building - - RemoveUnit(unit,build); // automaticly: CheckUnitToBeDrawn(unit) - build->CurrentSightRange=0; - unit->X=x; - unit->Y=y; - unit->Orders[0].Action=UnitActionStill; - unit->SubAction=0; + if (type->BuilderInside) { + // Place the builder inside the building + build->Data.Builded.Worker=unit; + RemoveUnit(unit,build); + build->CurrentSightRange=0; + unit->X=x; + unit->Y=y; + unit->Orders[0].Action=UnitActionStill; + unit->SubAction=0; + } else { + // Make the builder repair the newly spawned building. + unit->Orders[0].Action=UnitActionRepair; + unit->Orders[0].Goal=build; + unit->Orders[0].X=unit->Orders[0].Y=-1; + unit->Orders[0].RangeX=unit->Orders[0].RangeY=REPAIR_RANGE; + //unit->Orders[0].Type=unit->Orders[0].Arg1=NULL; + unit->SubAction=0; + unit->Wait=1; +// unit->Reset=1; + RefsDebugCheck( !build->Refs ); + build->Refs++; + UnitMarkSeen(unit); + // We need somebody to work on it. + build->Data.Builded.Sub=build->Data.Builded.Add=0; + build->HP=1; + } + build->Wait=CYCLES_PER_SECOND/6; + UpdateConstructionFrame(build); UnitMarkSeen(build); } @@ -303,14 +319,13 @@ global void HandleActionBuilded(Unit* unit) // if( unit->Data.Builded.Cancel ) { // Drop out unit - worker=unit->Data.Builded.Worker; - worker->Orders[0].Action=UnitActionStill; - unit->Data.Builded.Worker=NoUnitP; - worker->Reset=worker->Wait=1; - worker->SubAction=0; - - unit->Value=worker->Value; // worker holding value while building - DropOutOnSide(worker,LookingW,type->TileWidth,type->TileHeight); + if ((worker=unit->Data.Builded.Worker)) { + worker->Orders[0].Action=UnitActionStill; + unit->Data.Builded.Worker=NoUnitP; + worker->Reset=worker->Wait=1; + worker->SubAction=0; + DropOutOnSide(worker,LookingW,type->TileWidth,type->TileHeight); + } // Player gets back 75% of the original cost for a building. PlayerAddCostsFactor(unit->Player,unit->Stats->Costs, @@ -320,23 +335,26 @@ global void HandleActionBuilded(Unit* unit) return; } - // - // Fixed point HP calculation - // - unit->Data.Builded.Val-=unit->Data.Builded.Sub; - if( unit->Data.Builded.Val<0 ) { - unit->Data.Builded.Val+=unit->Stats->HitPoints; - unit->HP++; - unit->Data.Builded.Sum++; - } + if (type->BuilderInside) { + // + // Fixed point HP calculation + // + unit->Data.Builded.Val-=unit->Data.Builded.Sub; + if( unit->Data.Builded.Val<0 ) { + unit->Data.Builded.Val+=unit->Stats->HitPoints; + unit->HP++; + unit->Data.Builded.Sum++; + } - n=(unit->Stats->Costs[TimeCost]*CYCLES_PER_SECOND/6)/(SpeedBuild*5); - if( unit->Data.Builded.Add!=unit->Stats->HitPoints/(n?n:1) ) { - unit->Data.Builded.Add=unit->Stats->HitPoints/(n?n:1); - } + + n=(unit->Stats->Costs[TimeCost]*CYCLES_PER_SECOND/6)/(SpeedBuild*5); + if( unit->Data.Builded.Add!=unit->Stats->HitPoints/(n?n:1) ) { + unit->Data.Builded.Add=unit->Stats->HitPoints/(n?n:1); + } - unit->HP+=unit->Data.Builded.Add; - unit->Data.Builded.Sum+=unit->Data.Builded.Add; + unit->HP+=unit->Data.Builded.Add; + unit->Data.Builded.Sum+=unit->Data.Builded.Add; + } // // Check if building ready. Note we can build and repair. @@ -352,37 +370,49 @@ global void HandleActionBuilded(Unit* unit) unit->Constructed=0; unit->Frame=0; unit->Reset=unit->Wait=1; - worker=unit->Data.Builded.Worker; - worker->Orders[0].Action=UnitActionStill; - worker->SubAction=0; - worker->Reset=worker->Wait=1; - DropOutOnSide(worker,LookingW,type->TileWidth,type->TileHeight); - // - // Whe - // - if( type->MustBuildOnTop ) { + + if ((worker=unit->Data.Builded.Worker)) { + // Bye bye worker. + if (type->BuilderLost) { + // FIXME: enough? + LetUnitDie(worker); + // Drop out the worker. + } else { + worker->Orders[0].Action=UnitActionStill; + worker->SubAction=0; + worker->Reset=worker->Wait=1; + DropOutOnSide(worker,LookingW,type->TileWidth,type->TileHeight); + // + // If we can harvest from the new building, do it. + // + if (worker->Type->Harvester&&worker->Type->ResourceHarvested==type->GivesResource) { + CommandResource(worker,unit,0); + } + // + // Building lumber mill, let worker automatic chopping wood. + // + if( type->CanStore[WoodCost] ) { + CommandHarvest(worker,unit->X+unit->Type->TileWidth/2, + unit->Y+unit->Type->TileHeight/2,0); + } + } + } + + if( type->GivesResource ) { // FIXME: nobody: shouldn't this be already 0? - // It holds the number of units inside a resource. + // FIXME: wierd condition. + // FIXME: It holds the number of units inside a resource. unit->Data.Resource.Active=0; } - // - // If we can harvest from the new building, do it. - // - if (worker->Type->Harvester&&worker->Type->ResourceHarvested==type->GivesResource) { - CommandResource(worker,unit,0); - } - // - // Building lumber mill, let worker automatic chopping wood. - // - if( type->CanStore[WoodCost] ) { - CommandHarvest(worker,unit->X+unit->Type->TileWidth/2, - unit->Y+unit->Type->TileHeight/2,0); - } NotifyPlayer(unit->Player,NotifyGreen,unit->X,unit->Y, "New %s done", type->Name); if( unit->Player==ThisPlayer ) { - PlayUnitSound(worker,VoiceWorkCompleted); + if (worker) { + PlayUnitSound(worker,VoiceWorkCompleted); + } else { + PlayUnitSound(unit,VoiceBuilding); + } } else if( unit->Player->Ai ) { AiWorkComplete(worker,unit); } diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp index 7f266c217..c24b273f2 100644 --- a/src/action/action_follow.cpp +++ b/src/action/action_follow.cpp @@ -61,10 +61,6 @@ global void HandleActionFollow(Unit* unit) { Unit* goal; - DebugLevel3Fn("%d: %d %d,%d \n" _C_ UnitNumber(unit) _C_ - unit->Orders[0].Goal ? UnitNumber(unit->Orders[0].Goal) : -1 _C_ - unit->Orders[0].X _C_ unit->Orders[0].Y); - // // Reached target // @@ -88,11 +84,32 @@ global void HandleActionFollow(Unit* unit) } return; } - if( goal->X==unit->Orders[0].X && goal->Y==unit->Orders[0].Y ) { - unit->Reset=1; - unit->Wait=10; + + // Two posibilities, both broken. maybe we should change the animation system? + // FIXME: Unit doesn't decrease range +#if 0 + if( (goal->X==unit->Orders[0].X && goal->Y==unit->Orders[0].Y)||unit->State ) { + UnitShowAnimation(unit,unit->Type->Animations->Still); + // + // Sea and air units are floating up/down. + // + if( unit->Type->SeaUnit||unit->Type->AirUnit ) { + unit->IY=(MyRand()>>15)&1; + } return; } +#else + // FIXME:Unit doesn't animate. + if( (goal->X==unit->Orders[0].X && goal->Y==unit->Orders[0].Y) ) { + unit->Reset=1; + unit->Wait=10; + if ((unit->Orders[0].RangeX>1)||(unit->Orders[0].RangeY>1)) { + unit->Orders[0].RangeX=unit->Orders[0].RangeY=1; + unit->SubAction=0; + } + return; + } +#endif unit->SubAction=0; } @@ -189,7 +206,7 @@ global void HandleActionFollow(Unit* unit) } return; } - + if( !(goal=unit->Orders[0].Goal) ) {// goal has died unit->Wait=1; unit->SubAction=0; diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp index 056baba0d..90fd291ca 100644 --- a/src/action/action_move.cpp +++ b/src/action/action_move.cpp @@ -115,6 +115,7 @@ local int ActionMoveGeneric(Unit* unit,const Animation* anim) // // Transporter (un)docking? // + // FIXME: This is an ugly hack if( unit->Type->Transporter && ( (WaterOnMap(unit->X,unit->Y) && CoastOnMap(unit->X+xd,unit->Y+yd)) @@ -282,7 +283,7 @@ global void HandleActionMove(Unit* unit) DebugCheck( unit->State!=0 ); } - // FIXME: (mr-russ) Make a reachable goal here with GoalReachable... + // FIXME: (mr-russ) Make a reachable goal here with GoalReachable ... switch( DoActionMove(unit) ) { // reached end-point? case PF_UNREACHABLE: diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp index f4a7531dc..18e173e40 100644 --- a/src/action/action_resource.cpp +++ b/src/action/action_resource.cpp @@ -10,7 +10,7 @@ // /**@name action_resource.c - The generic resource action. */ // -// (c) Copyright 2001-2003 by Lutz Sammer +// (c) Copyright 2001-2003 by Lutz Sammer and Crestez Leonard // // 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 @@ -136,12 +136,7 @@ local int MoveToResource(Unit* unit) // Activate the resource // goal->Data.Resource.Active++; - DebugLevel3Fn("+%d\n" _C_ goal->Data.Resource.Active); - if( !goal->Frame ) { // show resource working - goal->Frame=1; - CheckUnitToBeDrawn(goal); - } UnitMarkSeen(goal); // // Place unit inside the resource @@ -191,10 +186,8 @@ local int WaitInResource(Unit* unit) source->Value-=unit->Type->ResourceCapacity; } - if( !--source->Data.Resource.Active ) { - source->Frame=0; - CheckUnitToBeDrawn(source); - } + source->Data.Resource.Active--; + DebugCheck(source->Data.Resource.Active<0); UnitMarkSeen(source); if( IsOnlySelected(source) ) { diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp index f6b8ea233..38a8bfc04 100644 --- a/src/action/action_still.cpp +++ b/src/action/action_still.cpp @@ -91,12 +91,12 @@ global void ActionStillGeneric(Unit* unit,int ground) UnitShowAnimation(unit,type->Animations->Still); // - // FIXME: this a workaround of a bad code. + // FIXME: this a workaround for some bad code. // UnitShowAnimation resets frame. // FIXME: the frames are hardcoded they should be configurable // if( unit->State==1 && type->GivesResource==GoldCost ) { - unit->Frame=!!unit->Data.Resource.Active; + unit->Frame=unit->Data.Resource.Active ? 1 : 0; } if( unit->State==1 && type->GivesResource==OilCost ) { unit->Frame=unit->Data.Resource.Active ? 2 : 0; @@ -242,7 +242,7 @@ global void ActionStillGeneric(Unit* unit,int ground) } // - // Land units: are turning left/right. + // Land units are turning left/right. // if( type->LandUnit ) { switch( (MyRand()>>8)&0x0FF ) { @@ -263,19 +263,10 @@ global void ActionStillGeneric(Unit* unit,int ground) } // - // Sea units: are floating up/down. - // - if( type->SeaUnit ) { + // Sea and air units are floating up/down. + // + if( unit->Type->SeaUnit||unit->Type->AirUnit ) { unit->IY=(MyRand()>>15)&1; - return; - } - - // - // Air units: are floating up/down. - // - if( type->AirUnit ) { - unit->IY=(MyRand()>>15)&1; - return; } } diff --git a/src/action/actions.cpp b/src/action/actions.cpp index 919f9a8f2..bf3ba5c16 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -88,7 +88,7 @@ global int UnitShowAnimation(Unit* unit,const Animation* animation) _C_ animation[state].Flags _C_ animation[state].Pixel _C_ animation[state].Frame _C_ animation[state].Sleep); DebugLevel3("Heading %d +%d,%d\n" _C_ unit->Direction _C_ unit->IX _C_ unit->IY); - + if( unit->Frame<0 ) { unit->Frame+=-animation[state].Frame; } else { @@ -398,7 +398,7 @@ global void UnitActions(void) HandleUnitAction(unit); DebugCheck( *tpos!=unit ); // Removed is evil. -#ifdef DEBUG +#ifdef DEBUG_wastes_disk_space // // Dump the unit to find the network unsyncron bug. // diff --git a/src/action/command.cpp b/src/action/command.cpp index 3d0d2ab69..c65004eec 100644 --- a/src/action/command.cpp +++ b/src/action/command.cpp @@ -678,6 +678,12 @@ global void CommandBuildBuilding(Unit* unit,int x,int y order->X=x; order->Y=y; } + if(!what->BuilderInside) { + // FIXME: n0body: brain damage. Walk around buggy moving to + // FIXME: the building position. + order->RangeX=what->TileWidth+10; + order->RangeY=what->TileWidth+10; + } order->Type=what; order->Arg1=NULL; } diff --git a/src/include/iolib.h b/src/include/iolib.h index bb58d1a00..8521378f7 100644 --- a/src/include/iolib.h +++ b/src/include/iolib.h @@ -67,12 +67,14 @@ typedef struct _filelist_ { } FileList; -#if !defined(USE_ZLIB) && !defined(USE_BZ2LIB) && !defined(USE_ZZIPLIB) +#if 0 && !defined(USE_ZLIB) && !defined(USE_BZ2LIB) && !defined(USE_ZZIPLIB) +// FIXME: This is broken, should write a CLopen for plain files +// FIXME: but we can avoid it anyway. // use plain file routines directly #define CLFile FILE -#define CLopen(file) fopen(file,"rb") +#define CLopen(file,whatever) fopen(file,"rwb") #define CLread(file,buf,len) fread(buf,1,len,file) #define CLseek(file,offset,whence) fseek(file,offset,whence) #define CLclose(file) fclose(file) diff --git a/src/include/unit.h b/src/include/unit.h index a7667d080..273878459 100644 --- a/src/include/unit.h +++ b/src/include/unit.h @@ -716,13 +716,13 @@ extern int ShowAttackRange; /// Flag: show attack range extern int ShowOrders; /// Flag: show orders of unit on map extern unsigned long ShowOrdersCount; /// Show orders for some time extern int HitPointRegeneration; /// Hit point regeneration for all units -extern int XpDamage; /// unit XP adds more damage to attacks +extern int XpDamage; /// unit XP adds more damage to attacks extern char EnableTrainingQueue; /// Config: training queues enabled extern char EnableBuildingCapture; /// Config: building capture enabled extern char RevealAttacker; /// Config: reveal attacker enabled extern const Viewport* CurrentViewport; /// CurrentViewport - /// Draw the selection -extern void (*DrawSelection)(const Unit*,const UnitType*,int,int); +extern void DrawUnitSelection(const Unit*); +extern void (*DrawSelection)(int,int,int,int,int); // in selection.c extern Unit* Selected[MaxSelectable]; /// currently selected units @@ -909,23 +909,17 @@ extern void DeadCacheRemove(Unit* unit,Unit** List ); // in unit_draw.c //-------------------- /// Draw nothing around unit -extern void DrawSelectionNone(const Unit* unit,const UnitType* type - ,int x,int y); +extern void DrawSelectionNone(int,int,int,int,int); /// Draw circle around unit -extern void DrawSelectionCircle(const Unit* unit,const UnitType* type - ,int x,int y); +extern void DrawSelectionCircle(int,int,int,int,int); /// Draw circle filled with alpha around unit -extern void DrawSelectionCircleWithTrans(const Unit* unit,const UnitType* type - ,int x,int y); +extern void DrawSelectionCircleWithTrans(int,int,int,int,int); /// Draw rectangle around unit -extern void DrawSelectionRectangle(const Unit* unit,const UnitType* type - ,int x,int y); +extern void DrawSelectionRectangle(int,int,int,int,int); /// Draw rectangle filled with alpha around unit -extern void DrawSelectionRectangleWithTrans(const Unit* unit - ,const UnitType* type,int x,int y); +extern void DrawSelectionRectangleWithTrans(int,int,int,int,int); /// Draw corners around unit -extern void DrawSelectionCorners(const Unit* unit,const UnitType* type - ,int x,int y); +extern void DrawSelectionCorners(int,int,int,int,int); /// Register CCL decorations features extern void DecorationCclRegister(void); diff --git a/src/include/unittype.h b/src/include/unittype.h index e82928174..4ae244e6f 100644 --- a/src/include/unittype.h +++ b/src/include/unittype.h @@ -583,6 +583,9 @@ struct _unit_type_ { unsigned CanCastSpell : 1; /// Unit is able to use spells. unsigned CanAttack : 1; /// Unit can attack. unsigned CanRepair : 1; /// Unit can repair . + unsigned BuilderInside : 1; /// The builder goes inside during the build. + unsigned BuilderLost : 1; /// The builder is lost after the build. + unsigned AutoBuildRate; /// The rate at which the building builds itself unsigned Tower : 1; /// Unit can attack, but not move. unsigned Hero : 1; /// Is hero only used for triggers . unsigned Volatile : 1; /// Invisiblity/unholy armor kills unit. diff --git a/src/sound/flac.cpp b/src/sound/flac.cpp index 63fd4e79f..86b22e44a 100644 --- a/src/sound/flac.cpp +++ b/src/sound/flac.cpp @@ -360,7 +360,7 @@ global Sample* LoadFlac(const char* name, int flags) FLAC__StreamDecoder* stream; FlacData *data; - if (!(f = CLopen(name))) { + if (!(f = CLopen(name,CL_OPEN_READ))) { fprintf(stderr, "Can't open file `%s'\n", name); return NULL; } @@ -374,7 +374,7 @@ global Sample* LoadFlac(const char* name, int flags) // FIXME: ugly way to seek to start of file CLclose(f); - if (!(f = CLopen(name))) { + if (!(f = CLopen(name,CL_OPEN_READ))) { fprintf(stderr, "Can't open file `%s'\n", name); return NULL; } diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp index d36ffeadf..6749c05bb 100644 --- a/src/ui/mainscr.cpp +++ b/src/ui/mainscr.cpp @@ -187,11 +187,12 @@ global void DrawUnitInfo(const Unit* unit) type=unit->Type; stats=unit->Stats; - IfDebug( +#ifdef DEBUG if( !type ) { DebugLevel1Fn(" FIXME: free unit selected\n"); return; - } ); + } +#endif // // Draw icon in upper left corner @@ -293,7 +294,7 @@ global void DrawUnitInfo(const Unit* unit) // Building under constuction. // if( unit->Orders[0].Action==UnitActionBuilded ) { - if( !OriginalBuilding ) { + if( !OriginalBuilding && unit->Data.Builded.Worker ) { // FIXME: Position must be configured! DrawUnitIcon(unit->Data.Builded.Worker->Player ,unit->Data.Builded.Worker->Type->Icon.Icon diff --git a/src/ui/mouse.cpp b/src/ui/mouse.cpp index fb4797aa3..e40995fd1 100644 --- a/src/ui/mouse.cpp +++ b/src/ui/mouse.cpp @@ -134,8 +134,10 @@ global void DoRightButton(int sx,int sy) // Right mouse with SHIFT appends command to old commands. // flush=!(KeyModifiers&ModifierShift); + + dest=UnitUnderCursor; - if( UnitUnderCursor && (dest=TransporterOnMapTile(x,y))) { + if( dest && dest->Type->Transporter ) { // n0b0dy: So we are clicking on a transporter. We have to: // 1) Flush the transporters orders. // 2) Tell the transporter to follow the units. We have to queue all @@ -153,7 +155,7 @@ global void DoRightButton(int sx,int sy) acknowledged=0; for( i=0; i<NumSelected; ++i ) { unit=Selected[i]; - // If we are telling units to board a tranasporter, + // If we are telling units to board a transporter, // don't give the transport extra orders. if (unit==desttransporter) { continue; @@ -170,41 +172,34 @@ global void DoRightButton(int sx,int sy) // // Control + right click on unit is follow anything. // - if( KeyModifiers&ModifierControl && UnitUnderCursor ) { - // FIXME: what todo if more than one unit on that tile? - dest=UnitOnMapTile(x,y); - if( dest ) { - if( dest!=unit ) { - dest->Blink=4; - SendCommandFollow(unit,dest,flush); - continue; - } - } + if( KeyModifiers&ModifierControl && dest && dest!=unit) { + dest->Blink=4; + SendCommandFollow(unit,dest,flush); + continue; } // // Enter transporters? // - if( UnitUnderCursor && (dest=TransporterOnMapTile(x,y))) { - if( dest->Player==unit->Player - && unit->Type->UnitType==UnitTypeLand ) { - dest->Blink=4; - DebugLevel0Fn("Board transporter\n"); - // Let the transporter move to passenger - SendCommandFollow(dest,unit,0); - SendCommandBoard(unit,-1,-1,dest,flush); - continue; - } + if( dest && dest->Type->Transporter && + dest->Player==unit->Player + && unit->Type->UnitType==UnitTypeLand ) { + dest->Blink=4; + DebugLevel0Fn("Board transporter\n"); + // Let the transporter move to the unit. And QUEUE!!! + SendCommandFollow(dest,unit,0); + SendCommandBoard(unit,-1,-1,dest,flush); + continue; } // - // Worker of human or orcs + // Handle resource workers. // if( action==MouseActionHarvest ) { // Return wood cutter home if( (type==UnitTypeOrcWorkerWithWood || type==UnitTypeHumanWorkerWithWood) && - (dest=ResourceDepositOnMap(x,y,WoodCost)) && + dest && dest->Type->CanStore[WoodCost] && dest->Player==unit->Player) { DebugLevel3("send to wood deposit.\n"); dest->Blink=4; @@ -218,11 +213,11 @@ global void DoRightButton(int sx,int sy) SendCommandHarvest(unit,x,y,flush); continue; } - if (unit->Type->Harvester&&UnitUnderCursor) { + if (unit->Type->Harvester && dest) { // Return a loaded harvester to deposit - if( (unit->Value>0) && - (dest=ResourceDepositOnMap(x,y,unit->Type->ResourceHarvested)) && - (dest->Player==unit->Player)) { + if( unit->Value>0 && + dest->Type->CanStore[unit->Type->ResourceHarvested] && + dest->Player==unit->Player) { dest->Blink=4; DebugLevel3Fn("Return to deposit.\n"); SendCommandReturnGoods(unit,dest,flush); @@ -230,31 +225,29 @@ global void DoRightButton(int sx,int sy) } // Go and harvest if( (unit->Value<unit->Type->ResourceCapacity) && - (dest=ResourceOnMap(x,y,unit->Type->ResourceHarvested)) && - ((dest->Player==unit->Player) || - (dest->Player->Player==PlayerMax-1))) { + dest->Type->GivesResource==unit->Type->ResourceHarvested && + (dest->Player==unit->Player || + dest->Player->Player==PlayerMax-1)) { dest->Blink=4; SendCommandResource(unit,dest,flush); continue; } } // Go and repair - if ( (unit->Type->CanRepair) && - (UnitUnderCursor) && - (dest=RepairableOnMapTile(x,y)) && - ((dest->Player==unit->Player) || (IsAllied(dest->Player,dest)))) { + if ( (unit->Type->CanRepair) && dest && + (dest->Type->Building || dest->Type->Transporter) && + dest->HP < dest->Stats->HitPoints && + (dest->Player==unit->Player || IsAllied(dest->Player,dest)) ) { dest->Blink=4; SendCommandRepair(unit,x,y,dest,flush); continue; } // Follow another unit - if( UnitUnderCursor && (dest=UnitOnMapTile(x,y)) ) { - if( (dest->Player==unit->Player || IsAllied(unit->Player,dest)) - && dest!=unit ) { - dest->Blink=4; - SendCommandFollow(unit,dest,flush); - continue; - } + if( UnitUnderCursor && dest && dest!=unit && + (dest->Player==unit->Player || IsAllied(unit->Player,dest)) ) { + dest->Blink=4; + SendCommandFollow(unit,dest,flush); + continue; } // Move SendCommandMove(unit,x,y,flush); @@ -265,19 +258,16 @@ global void DoRightButton(int sx,int sy) // Fighters // if( action==MouseActionDemolish || action==MouseActionAttack ) { - if( UnitUnderCursor ) { - // Picks the enemy with highest priority and can be attacked - dest=TargetOnMapTile(unit, x, y); - if( dest ) { - if( IsEnemy(unit->Player,dest) ) { - dest->Blink=4; - if( action==MouseActionDemolish ) { - SendCommandDemolish(unit,x,y,dest,flush); - } else { - SendCommandAttack(unit,x,y,dest,flush); - } - continue; + if( dest ) { + if( IsEnemy(unit->Player,dest) ) { + dest->Blink=4; + if( action==MouseActionDemolish ) { + // This is for demolition squads and such + SendCommandDemolish(unit,x,y,dest,flush); + } else { + SendCommandAttack(unit,x,y,dest,flush); } + continue; } if( WallOnMap(x,y) ) { @@ -296,14 +286,11 @@ global void DoRightButton(int sx,int sy) } } - dest=UnitOnMapTile(x,y); - if( dest ) { - if( (dest->Player==unit->Player - || IsAllied(unit->Player,dest)) && dest!=unit ) { - dest->Blink=4; - SendCommandFollow(unit,dest,flush); - continue; - } + if( (dest->Player==unit->Player||IsAllied(unit->Player,dest)) + && dest!=unit ) { + dest->Blink=4; + SendCommandFollow(unit,dest,flush); + continue; } #ifdef NEW_SHIPS @@ -334,16 +321,12 @@ global void DoRightButton(int sx,int sy) } // FIXME: attack/follow/board ... - if( action==MouseActionMove || action==MouseActionSail ) { - if( UnitUnderCursor && (dest=UnitOnMapTile(x,y)) ) { - // Follow allied units, but not self. - if( (dest->Player==unit->Player - || IsAllied(unit->Player,dest)) && dest!=unit ) { - dest->Blink=4; - SendCommandFollow(unit,dest,flush); - continue; - } - } + if( (action==MouseActionMove || action==MouseActionSail) && + (dest && dest!=unit) && + (dest->Player==unit->Player|| IsAllied(unit->Player,dest))) { + dest->Blink=4; + SendCommandFollow(unit,dest,flush); + continue; } // @@ -361,13 +344,13 @@ global void DoRightButton(int sx,int sy) #endif if (type->Building) { - if( UnitUnderCursor && (dest=ResourceOnMap(x,y,OilCost)) ) { + if( dest && dest->Type->GivesResource==OilCost ) { dest->Blink=4; DebugLevel3("RALY POINT TO PLATFORM\n"); SendCommandResource(Selected[i],dest,!(KeyModifiers&ModifierShift)); continue; } - if( UnitUnderCursor && (dest=ResourceOnMap(x,y,GoldCost)) ) { + if( dest && dest->Type->GivesResource==GoldCost ) { dest->Blink=4; DebugLevel3("RALY POINT TO GOLD-MINE\n"); SendCommandResource(Selected[i],dest,!(KeyModifiers&ModifierShift)); @@ -788,23 +771,17 @@ local void SendRepair(int sx,int sy) x=sx/TileSizeX; y=sy/TileSizeY; - if( UnitUnderCursor ) { - dest=RepairableOnMapTile(x,y); - } else { - dest=NoUnitP; - } - for( i=0; i<NumSelected; ++i ) { - unit=Selected[i]; - if( unit->Type->CanRepair ) { - // FIXME: Should move test in repairable - if( dest && dest->Type && (dest->Player==unit->Player - || IsAllied(unit->Player,dest)) ) { + // Check if the dest is repairable! + if( (dest=UnitUnderCursor) && (dest->HP<dest->Stats->HitPoints) && + (dest->Type->Building || dest->Type->Transporter) && + (dest->Player==ThisPlayer||IsAllied(ThisPlayer,dest))) { + for( i=0; i<NumSelected; ++i ) { + unit=Selected[i]; + if( unit->Type->CanRepair ) { SendCommandRepair(unit,x,y,dest,!(KeyModifiers&ModifierShift)); } else { - SendCommandRepair(unit,x,y,NoUnitP,!(KeyModifiers&ModifierShift)); + DebugLevel0Fn("Non-worker repairs\n"); } - } else { - DebugLevel0Fn("Non-worker repairs\n"); } } } @@ -812,45 +789,39 @@ local void SendRepair(int sx,int sy) /** ** Send selected units to point. ** -** @param x X map tile position. -** @param y Y map tile position. +** @param sx X screen tile position. +** @param sy Y screen tile position. ** ** @todo To reduce the CPU load for pathfinder, we should check if ** the destination is reachable and handle nice group movements. */ -local void SendMove(int x,int y) +local void SendMove(int sx,int sy) { int i; int flush; Unit* unit; Unit* transporter; - if( UnitUnderCursor ) { - transporter=TransporterOnMapTile(x,y); + // Move to a transporter. + if( (transporter=UnitUnderCursor) && + (transporter->Type->Transporter) && + (transporter->Player==ThisPlayer)){ + SendCommandStopUnit(transporter); } else { - transporter=NoUnitP; + transporter=NULL; } + flush=!(KeyModifiers&ModifierShift); for( i=0; i<NumSelected; ++i ) { unit=Selected[i]; - if( transporter && transporter->Player==unit->Player - && unit->Type->UnitType==UnitTypeLand ) { + if( transporter && unit->Type->UnitType==UnitTypeLand ) { transporter->Blink=4; DebugLevel3Fn("Board transporter\n"); - // Let the transporter move to passenger - // It should do nothing and not already on coast. - // FIXME: perhaps force move if not reachable. - if( transporter->Orders[0].Action==UnitActionStill - && transporter->OrderCount==1 - && !CoastOnMap(transporter->X,transporter->Y) ) { - SendCommandFollow(transporter,unit,FlushCommands); - } + SendCommandFollow(transporter,unit,0); SendCommandBoard(unit,-1,-1,transporter,flush); } else { -// if( !unit->Type->Building ) { - SendCommandMove(unit,x,y,flush); -// } + SendCommandMove(unit,sx/TileSizeX,sy/TileSizeY,flush); } } } @@ -882,8 +853,7 @@ local void SendAttack(int sx,int sy) for( i=0; i<NumSelected; i++ ) { unit=Selected[i]; if( unit->Type->CanAttack || unit->Type->Building ) { - if( UnitUnderCursor - && (dest=TargetOnMapTile(unit,x,y)) ) { + if( (dest=UnitUnderCursor) && CanTarget(unit->Type,dest->Type)) { DebugLevel3Fn("Attacking %p\n" _C_ dest); dest->Blink=4; } else { @@ -901,10 +871,10 @@ local void SendAttack(int sx,int sy) /** ** Send the current selected group ground attacking. ** -** @param x X map tile position. -** @param y Y map tile position. +** @param sx X screen map position. +** @param sy Y screen map position. */ -local void SendAttackGround(int x,int y) +local void SendAttackGround(int sx,int sy) { int i; Unit* unit; @@ -912,25 +882,26 @@ local void SendAttackGround(int x,int y) for( i=0; i<NumSelected; ++i ) { unit=Selected[i]; if( unit->Type->CanAttack ) { - SendCommandAttackGround(unit,x,y,!(KeyModifiers&ModifierShift)); + SendCommandAttackGround(unit,sx/TileSizeX,sy/TileSizeY,!(KeyModifiers&ModifierShift)); } else { - SendCommandMove(unit,x,y,!(KeyModifiers&ModifierShift)); + SendCommandMove(unit,sx/TileSizeX,sy/TileSizeY,!(KeyModifiers&ModifierShift)); } } } /** ** Let units patrol between current postion and the selected. +** @param sx X screen map position. +** @param sy Y screen map position. */ -local void SendPatrol(int x,int y) +local void SendPatrol(int sx,int sy) { int i; Unit* unit; for( i=0; i<NumSelected; i++ ) { unit=Selected[i]; - // FIXME: Can the unit patrol ? - SendCommandPatrol(unit,x,y,!(KeyModifiers&ModifierShift)); + SendCommandPatrol(unit,sx/TileSizeX,sy/TileSizeY,!(KeyModifiers&ModifierShift)); } } @@ -954,15 +925,12 @@ local void SendDemolish(int sx,int sy) unit=Selected[i]; if( unit->Type->Volatile ) { // FIXME: choose correct unit no flying ... - if( UnitUnderCursor ) { - dest=TargetOnMapTile(unit,x,y); - if( dest==unit ) { // don't let a unit self destruct - dest=NoUnitP; - } + if( (dest=UnitUnderCursor) && CanTarget(unit->Type,dest->Type)) { + dest->Blink=4; } else { dest=NoUnitP; } - SendCommandDemolish(unit,x,y,dest,!(KeyModifiers&ModifierShift)); + SendCommandDemolish(unit,sx/TileSizeX,sy/TileSizeY,dest,!(KeyModifiers&ModifierShift)); } else { DebugLevel0Fn("can't demolish %p\n" _C_ unit); } @@ -972,46 +940,45 @@ local void SendDemolish(int sx,int sy) /** ** Let units harvest wood/mine gold/haul oil ** -** @param x X map coordinate of the destination -** @param y Y map coordinate of the destination +** @param sx X screen map position +** @param sy Y screen map position ** ** @see Selected */ -local void SendHarvest(int x,int y) +local void SendHarvest(int sx,int sy) { int i; Unit* dest; for( i=0; i<NumSelected; ++i ) { - if( UnitUnderCursor && (dest=ResourceOnMap(x,y,OilCost)) ) { + DebugCheck(!Selected[i]->Type->Harvester); + if ((dest=UnitUnderCursor) && + (Selected[i]->Type->ResourceHarvested==dest->Type->GivesResource)) { dest->Blink=4; - DebugLevel3("PLATFORM\n"); + DebugLevel3("RESOURCE\n"); SendCommandResource(Selected[i],dest,!(KeyModifiers&ModifierShift)); continue; } - if( UnitUnderCursor && (dest=ResourceOnMap(x,y,GoldCost)) ) { - dest->Blink=4; - DebugLevel3("GOLD-MINE\n"); - SendCommandResource(Selected[i],dest,!(KeyModifiers&ModifierShift)); - continue; + if( IsMapFieldExplored(Selected[i]->Player,sx/TileSizeX,sy/TileSizeY) && + ForestOnMap(sx/TileSizeX,sy/TileSizeY) ) { + SendCommandHarvest(Selected[i],sx/TileSizeY,sy/TileSizeY,!(KeyModifiers&ModifierShift)); } - SendCommandHarvest(Selected[i],x,y,!(KeyModifiers&ModifierShift)); } } /** ** Send selected units to unload passengers. ** -** @param x X map tile position. -** @param y Y map tile position. +** @param sx X screen map position. +** @param sy Y screen map position. */ -local void SendUnload(int x,int y) +local void SendUnload(int sx,int sy) { int i; for( i=0; i<NumSelected; i++ ) { // FIXME: not only transporter selected? - SendCommandUnload(Selected[i],x,y,NoUnitP + SendCommandUnload(Selected[i],sx/TileSizeX,sy/TileSizeY,NoUnitP ,!(KeyModifiers&ModifierShift)); } } @@ -1038,11 +1005,9 @@ local void SendSpellCast(int sx, int sy) x=sx/TileSizeX; y=sy/TileSizeY; - if( UnitUnderCursor ) { - dest=UnitOnMapTile(x, y); - } else { - dest=NoUnitP; - } + + dest=UnitUnderCursor; + DebugLevel3Fn("SpellCast on: %p (%d,%d)\n" _C_ dest _C_ x _C_ y); /* NOTE: Vladi: This is a high-level function, it sends target spot and unit @@ -1056,6 +1021,7 @@ local void SendSpellCast(int sx, int sy) } if( dest && unit==dest ) { continue; // no unit can cast spell on himself + // n0b0dy: why not? } #ifndef NEW_UI // CursorValue here holds the spell type id @@ -1072,10 +1038,8 @@ local void SendSpellCast(int sx, int sy) /** ** Send a command to selected units. ** -** @param sx X screen map position in pixels. -** @param sy Y screen map position in pixels. -** -** @todo pure chaos the arguments of the Send... functions are no equal. +** @param sx X screen map position +** @param sy Y screen map position */ local void SendCommand(int sx, int sy) { @@ -1091,7 +1055,7 @@ local void SendCommand(int sx, int sy) #endif switch( CursorAction ) { case ButtonMove: - SendMove(x,y); + SendMove(sx,sy); break; case ButtonRepair: SendRepair(sx,sy); @@ -1100,16 +1064,16 @@ local void SendCommand(int sx, int sy) SendAttack(sx,sy); break; case ButtonAttackGround: - SendAttackGround(x,y); + SendAttackGround(sx,sy); break; case ButtonPatrol: - SendPatrol(x,y); + SendPatrol(sx,sy); break; case ButtonHarvest: - SendHarvest(x,y); + SendHarvest(sx,sy); break; case ButtonUnload: - SendUnload(x,y); + SendUnload(sx,sy); break; case ButtonDemolish: SendDemolish(sx,sy); diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp index 166c5b12c..025696ac6 100644 --- a/src/unit/script_unittype.cpp +++ b/src/unit/script_unittype.cpp @@ -377,6 +377,13 @@ local SCM CclDefineUnitType(SCM list) } else if( gh_eq_p(value,gh_symbol2scm("building")) ) { type->Building=1; + } else if( gh_eq_p(value,gh_symbol2scm("builder-inside")) ) { + type->BuilderInside=1; + } else if( gh_eq_p(value,gh_symbol2scm("builder-lost")) ) { + type->BuilderLost=1; + } else if( gh_eq_p(value,gh_symbol2scm("auto-build-rate")) ) { + type->AutoBuildRate=gh_scm2int(gh_car(list)); + list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("shore-building")) ) { type->ShoreBuilding=1; } else if( gh_eq_p(value,gh_symbol2scm("land-unit")) ) { diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp index f8f0f1c74..558645db6 100644 --- a/src/unit/unit_draw.cpp +++ b/src/unit/unit_draw.cpp @@ -87,13 +87,12 @@ global int ShowManaBackgroundLong; /** ** Show that units are selected. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void (*DrawSelection)(const Unit* unit,const UnitType* type,int x,int y) - =DrawSelectionNone; +global void (*DrawSelection)(int color,int x1,int y1,int x2,int y2) + =DrawSelectionNone; /*---------------------------------------------------------------------------- -- Functions @@ -110,11 +109,10 @@ global const Viewport* CurrentViewport; /// FIXME: quick hack for split screen ** Choose color for selection. ** ** @param unit Pointer to the unit. -** @param type Type of the unit. ** ** @return Color for selection, or -1 if not selected. */ -local int SelectionColor(const Unit* unit,const UnitType* type) +local int SelectionColor(const Unit* unit) { if( unit->Selected || (unit->Blink&1) ) { if( unit->Player->Player==PlayerNumNeutral ) { @@ -131,205 +129,130 @@ local int SelectionColor(const Unit* unit,const UnitType* type) } // If building mark all own buildings - if( CursorBuilding && type->Building && unit->Player==ThisPlayer ) { + if( CursorBuilding && unit->Type->Building && unit->Player==ThisPlayer ) { return ColorGray; } return -1; } +/** +** Show selection marker around an unit. +** +** @param unit Pointer to unit. +*/ +global void DrawUnitSelection(const Unit* unit) +{ + int color; + int x; + int y; + + color=SelectionColor(unit); + if (color<0) { + return; + } + x=Map2ViewportX(CurrentViewport,unit->X)+unit->IX + +unit->Type->TileWidth*TileSizeX/2-unit->Type->BoxWidth/2; + y=Map2ViewportY(CurrentViewport,unit->Y)+unit->IY + +unit->Type->TileHeight*TileSizeY/2-unit->Type->BoxHeight/2; + DrawSelection(color,x,y,x+unit->Type->BoxWidth,y+unit->Type->BoxHeight); +} + /** ** Don't show selected units. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionNone(const Unit* unit __attribute__((unused)), - const UnitType* type __attribute__((unused)), - int x __attribute__((unused)),int y __attribute__((unused))) +global void DrawSelectionNone(int color,int x1,int y1,int x2,int y2) +/*global void DrawSelectionNone(int color __attribute__((unused)), + int x1 __attribute__((unused)),int y1 __attribute__((unused)), + int x2 __attribute__((unused)),int y2 __attribute__((unused)))*/ { } /** ** Show selected units with circle. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionCircle(const Unit* unit,const UnitType* type - ,int x,int y) +global void DrawSelectionCircle(int color,int x1,int x2,int y1,int y2) { - int color; - - // - // Select color for the circle. - // - if( (color=SelectionColor(unit,type))<0 ) { - return; - } - VideoDrawCircleClip(color - ,x+type->TileWidth*TileSizeX/2 - ,y+type->TileHeight*TileSizeY/2 - ,min(type->BoxWidth,type->BoxHeight)/2); - - VideoDrawCircleClip(color - ,x+type->TileWidth*TileSizeX/2 - ,y+type->TileHeight*TileSizeY/2 - ,min(type->BoxWidth+2,type->BoxHeight+2)/2); + DebugCheck(color<0); + VideoDrawCircleClip(color,(x1+x2)/2,(y1+y2)/2, + min((x2-x1)/2,(y2-y1)/2)); + VideoDrawCircleClip(color,(x1+x2)/2,(y1+y2)/2, + min((x2-x1)/2,(y2-y1)/2)+2); } /** ** Show selected units with circle. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionCircleWithTrans(const Unit* unit,const UnitType* type - ,int x,int y) -{ - int color; - - // - // Select color for the circle. - // - if( (color=SelectionColor(unit,type))<0 ) { - return; - } - VideoDrawCircleClip(color - ,x+type->TileWidth*TileSizeX/2 - ,y+type->TileHeight*TileSizeY/2 - ,min(type->BoxWidth,type->BoxHeight)/2); - - VideoFill75TransCircleClip(color - ,x+type->TileWidth*TileSizeX/2 - ,y+type->TileHeight*TileSizeY/2 - ,min(type->BoxWidth-2,type->BoxHeight-2)/2); +global void DrawSelectionCircleWithTrans(int color,int x1,int y1,int x2,int y2) +{ + DebugCheck(color<0); + VideoFill75TransCircleClip(color,(x1+x2)/2,(y1+y2)/2, + min((x2-x1)/2,(y2-y1)/2)-2); + VideoDrawCircleClip(color,(x1+x2)/2,(y1+y2)/2, + min((x2-x1)/2,(y2-y1)/2)); } /** ** Draw selected rectangle around the unit. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionRectangle(const Unit* unit,const UnitType* type - ,int x,int y) +global void DrawSelectionRectangle(int color,int x1,int y1,int x2,int y2) { - int color; - - // - // Select color for the rectangle - // - if( (color=SelectionColor(unit,type))<0 ) { - return; - } - - VideoDrawRectangleClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,type->BoxWidth - ,type->BoxHeight); + DebugCheck(color<0); + VideoDrawRectangleClip(color,x1,y1,x2-x1,y2-y1); } /** ** Draw selected rectangle around the unit. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionRectangleWithTrans(const Unit* unit - ,const UnitType* type,int x,int y) +global void DrawSelectionRectangleWithTrans(int color,int x1,int y1,int x2,int y2) { - int color; - - // - // Select color for the rectangle - // - if( (color=SelectionColor(unit,type))<0 ) { - return; - } - - VideoDrawRectangleClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,type->BoxWidth - ,type->BoxHeight); - VideoFill75TransRectangleClip(color - ,x+1+(type->TileWidth*TileSizeX-type->BoxWidth)/2 - ,y+1+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,type->BoxWidth-2 - ,type->BoxHeight-2); + DebugCheck(color<0); + VideoDrawRectangleClip(color,x1,y1,x2-x1,y2-y1); + VideoFill75TransRectangleClip(color,x1+1,y1+1,x2-x1-2,y2-y1-2); } /** ** Draw selected corners around the unit. ** -** @param unit Pointer to the unit. -** @param type Type of the unit. -** @param x Screen X position of the unit. -** @param y Screen Y position of the unit. +** @param color +** @param x1,y1 Coordinates of the top left corner. +** @param x2,y2 Coordinates of the bottom right corner. */ -global void DrawSelectionCorners(const Unit* unit,const UnitType* type - ,int x,int y) +global void DrawSelectionCorners(int color,int x1,int y1,int x2,int y2) { - int color; + DebugCheck(color<0); #define CORNER_PIXELS 6 - // - // Select color for the rectangle - // - if( (color=SelectionColor(unit,type))<0 ) { - return; - } + VideoDrawVLineClip(color,x1,y1,CORNER_PIXELS); + VideoDrawHLineClip(color,x1+1,y1,CORNER_PIXELS-1); - VideoDrawVLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,CORNER_PIXELS); - VideoDrawHLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+1 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,CORNER_PIXELS-1); + VideoDrawVLineClip(color,x2,y1,CORNER_PIXELS); + VideoDrawHLineClip(color,x2-CORNER_PIXELS+1,y1,CORNER_PIXELS-1); - VideoDrawVLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+type->BoxWidth - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,CORNER_PIXELS); - VideoDrawHLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+type->BoxWidth - -CORNER_PIXELS+1 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2 - ,CORNER_PIXELS-1); + VideoDrawVLineClip(color,x1,y2-CORNER_PIXELS+1,CORNER_PIXELS); + VideoDrawHLineClip(color,x1,y2,CORNER_PIXELS-1); - VideoDrawVLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2+type->BoxHeight - -CORNER_PIXELS+1 - ,CORNER_PIXELS); - VideoDrawHLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+1 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2+type->BoxHeight - ,CORNER_PIXELS-1); - - VideoDrawVLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+type->BoxWidth - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2+type->BoxHeight - -CORNER_PIXELS+1 - ,CORNER_PIXELS); - VideoDrawHLineClip(color - ,x+(type->TileWidth*TileSizeX-type->BoxWidth)/2+type->BoxWidth - -CORNER_PIXELS+1 - ,y+(type->TileHeight*TileSizeY-type->BoxHeight)/2+type->BoxHeight - ,CORNER_PIXELS-1); + VideoDrawVLineClip(color,x2,y2-CORNER_PIXELS+1,CORNER_PIXELS); + VideoDrawHLineClip(color,x2-CORNER_PIXELS+1,y2,CORNER_PIXELS-1); } /** @@ -1406,6 +1329,31 @@ global void DrawPath(const Unit* unit) } } +/** +** Get the location of an order. +** +** @param order Pointer to order. +** @param x Resulting screen X cordinate. +** @param x Resulting screen Y cordinate. +*/ +local void GetOrderPosition(const Order* order,int* x,int* y) +{ + Unit* goal; + // FIXME: n0body: Check for goal gone? + if ((goal=order->Goal)&&(!goal->Removed)) { + *x = Map2ViewportX(CurrentViewport,goal->X)+goal->IX+goal->Type->TileWidth*TileSizeX/2; + *y = Map2ViewportY(CurrentViewport,goal->Y)+goal->IY+goal->Type->TileHeight*TileSizeY/2; + } else { + *x = Map2ViewportX(CurrentViewport,order->X)+TileSizeX/2; + *y = Map2ViewportY(CurrentViewport,order->Y)+TileSizeY/2; + if (order->Action==UnitActionBuild) { + // The -1 is because of what we have above. + *x += (order->Type->TileWidth-1)*TileSizeX/2; + *y += (order->Type->TileHeight-1)*TileSizeY/2; + } + } +} + /** ** Show the order on map. ** @@ -1423,15 +1371,8 @@ local void ShowSingleOrder(const Unit* unit, int x1, int y1, const Order* order) int dest; const Unit* goal; - if ((goal = order->Goal) && goal->Type) { - x2 = Map2ViewportX(CurrentViewport, - goal->X) + goal->IX + goal->Type->TileWidth * TileSizeX / 2; - y2 = Map2ViewportY(CurrentViewport, - goal->Y) + goal->IY + goal->Type->TileHeight * TileSizeY / 2; - } else { - x2 = Map2ViewportX(CurrentViewport, order->X ) + TileSizeX / 2; - y2 = Map2ViewportY(CurrentViewport, order->Y ) + TileSizeY / 2; - } + GetOrderPosition(order,&x2,&y2); + dest = 0; switch (order->Action) { case UnitActionNone: @@ -1513,6 +1454,8 @@ local void ShowSingleOrder(const Unit* unit, int x1, int y1, const Order* order) break; case UnitActionBuild: + DrawSelection(ColorGray,x2-order->Type->BoxWidth/2,y2-order->Type->BoxHeight/2, + x2+order->Type->BoxWidth/2,y2+order->Type->BoxHeight/2); e_color = color = ColorGreen; dest = 1; break; @@ -1563,16 +1506,25 @@ local void ShowOrder(const Unit* unit) { int x1; int y1; + int i; + Unit *goal; if (unit->Destroyed) { return; } + x1 = Map2ViewportX(CurrentViewport, unit->X) + unit->IX + unit->Type->TileWidth * TileSizeX / 2; y1 = Map2ViewportY(CurrentViewport, unit->Y) + unit->IY + unit->Type->TileHeight * TileSizeY / 2; ShowSingleOrder(unit, x1, y1, unit->Orders); +#if 1 + for (i=1;i<unit->OrderCount;i++) { + GetOrderPosition(unit->Orders+i-1,&x1,&y1); + ShowSingleOrder(unit,x1,y1,unit->Orders+i); + } +#endif if (unit->Type->Building) { ShowSingleOrder(unit, x1, y1, &unit->NewOrder); } @@ -1815,7 +1767,7 @@ global void DrawBuilding(const Unit* unit) // // Show that the unit is selected // - DrawSelection(unit,type,x,y); + DrawUnitSelection(unit); // // Buildings under construction/upgrade/ready. @@ -1876,7 +1828,7 @@ global void DrawUnit(const Unit* unit) // // Show that the unit is selected // - DrawSelection(unit,type,x,y); + DrawUnitSelection(unit); GraphicUnitPixels(unit,type->Sprite); DrawUnitType(type,unit->Frame,x,y); diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp index 1f3561dad..69b9b22b0 100644 --- a/src/unit/unit_find.cpp +++ b/src/unit/unit_find.cpp @@ -245,6 +245,8 @@ global Unit* TargetOnMapTile(const Unit* source,int tx,int ty) type=unit->Type; if( tx<unit->X || tx>=unit->X+type->TileWidth || ty<unit->Y || ty>=unit->Y+type->TileHeight ) { + // When does that happen??? + DebugLevel0("This is a wierd world"); continue; } if( !CanTarget(source->Type,unit->Type) ) { diff --git a/src/unit/unittype.cpp b/src/unit/unittype.cpp index f8eda76b6..02bd9f0d5 100644 --- a/src/unit/unittype.cpp +++ b/src/unit/unittype.cpp @@ -840,7 +840,16 @@ local void SaveUnitType(CLFile* file,const UnitType* type,int all) } if( type->Building ) { - CLprintf(file," 'building\n"); + CLprintf(file," 'building"); + } + if( type->BuilderInside ) { + CLprintf(file," 'builder-inside"); + } + if( type->BuilderLost ) { + CLprintf(file," 'builder-lost"); + } + if( type->AutoBuildRate ) { + CLprintf(file," 'auto-build-rate"); } if( type->ShoreBuilding ) { CLprintf(file," 'shore-building\n"); @@ -870,6 +879,9 @@ local void SaveUnitType(CLFile* file,const UnitType* type,int all) if( type->Transporter ) { CLprintf(file," 'transporter\n"); } + if( type->Transporter ) { + CLprintf(file," 'max-on-board %d\n",type->MaxOnBoard); + } if( type->CowerWorker ) { CLprintf(file," 'cower-worker\n");