Show entire path while pressing shift.

Tweak code in mouse.c(better when clicking on a moving unit).
Adding building methods.
Other minor tweaks.
This commit is contained in:
n0body 2003-08-21 06:12:04 +00:00
parent cd18c267ec
commit 946290f823
20 changed files with 445 additions and 465 deletions

View file

@ -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).

View file

@ -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;

View file

@ -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.

View file

@ -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);
}

View file

@ -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;

View file

@ -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:

View file

@ -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) ) {

View file

@ -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;
}
}

View file

@ -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.
//

View file

@ -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;
}

View file

@ -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)

View file

@ -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);

View file

@ -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.

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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")) ) {

View file

@ -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);

View file

@ -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) ) {

View file

@ -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");