diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp index a0927e4fa..bcdc3ae6c 100644 --- a/src/action/action_move.cpp +++ b/src/action/action_move.cpp @@ -192,7 +192,11 @@ local int ActionMoveGeneric(Unit* unit,const Animation* anim) // unit->IX+=xd*anim[state].Pixel; unit->IY+=yd*anim[state].Pixel; - unit->Frame+=anim[state].Frame; + if( unit->Frame<0 ) { + unit->Frame+=-anim[state].Frame; + } else { + unit->Frame+=anim[state].Frame; + } unit->Wait=anim[state].Sleep; if( unit->Slow ) { // unit is slowed down unit->Wait<<=1; diff --git a/src/action/actions.cpp b/src/action/actions.cpp index 44eb7cea0..7e293b1ae 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -86,7 +86,11 @@ global int UnitShowAnimation(Unit* unit,const Animation* animation) _C_ animation[state].Frame _C_ animation[state].Sleep); DebugLevel3("Heading %d +%d,%d\n" _C_ unit->Direction _C_ unit->IX _C_ unit->IY); - unit->Frame+=animation[state].Frame; + if( unit->Frame<0 ) { + unit->Frame+=-animation[state].Frame; + } else { + unit->Frame+=animation[state].Frame; + } unit->IX+=animation[state].Pixel; unit->IY+=animation[state].Pixel; unit->Wait=animation[state].Sleep; diff --git a/src/include/missile.h b/src/include/missile.h index fca7dd1da..5fda8848c 100644 --- a/src/include/missile.h +++ b/src/include/missile.h @@ -84,6 +84,10 @@ ** @note There is currently a limit of 127 sprite frames, which ** can be lifted if needed. ** +** MissileType::NumDirections +** +** Number of directions missile can face. +** ** MissileType::FiredSound ** ** Sound of the missile, if fired. @note currently not used. @@ -328,6 +332,7 @@ struct _missile_type_ { unsigned Width; /// missile width in pixels unsigned Height; /// missile height in pixels unsigned SpriteFrames; /// number of sprite frames in graphic + int NumDirections; /// number of directions missile can face // FIXME: FireSound defined but not used! SoundConfig FiredSound; /// fired sound diff --git a/src/include/unit.h b/src/include/unit.h index 7ae5a5573..8256494d8 100644 --- a/src/include/unit.h +++ b/src/include/unit.h @@ -142,7 +142,7 @@ ** Unit::SeenFrame ** ** Graphic image (see Unit::Frame) what the player on this -** computer has last seen. If -1 (0xFF) the player haven't seen +** computer has last seen. If UnitNotSeen the player haven't seen ** this unit yet. ** ** Unit::Direction @@ -455,6 +455,7 @@ enum _directions_ { }; #define NextDirection 32 /// Next direction N->NE->E... +#define UnitNotSeen 0x7fffffff /// Unit not seen, used by Unit::SeenFrame /// The big unit structure struct _unit_ { @@ -478,8 +479,8 @@ struct _unit_ { UnitColors Colors; /// Player colors char IX; /// X image displacement to map position char IY; /// Y image displacement to map position - unsigned Frame : 8; /// Image frame: high bit used for flip - unsigned SeenFrame : 8; /// last seen frame/stage of buildings + int Frame; /// Image frame: <0 is mirrored + int SeenFrame; /// last seen frame/stage of buildings unsigned Direction : 8; /// angle (0-255) unit looking diff --git a/src/include/unittype.h b/src/include/unittype.h index e12660b94..f3ae87897 100644 --- a/src/include/unittype.h +++ b/src/include/unittype.h @@ -158,6 +158,10 @@ ** ** Selected box size height ** +** UnitType::NumDirections +** +** Number of directions the unit can face +** ** UnitType::MinAttackRange ** ** Minimal attack range @@ -425,7 +429,7 @@ typedef struct _animation_ { unsigned char Flags; /// Flags for actions signed char Pixel; /// Change the position in pixels unsigned char Sleep; /// Wait for next animation - unsigned char Frame; /// Sprite-frame to display + int Frame; /// Sprite-frame to display } Animation; #define AnimationRestart 1 /// Restart animation @@ -497,6 +501,7 @@ struct _unit_type_ { int TileHeight; /// Tile size on map height int BoxWidth; /// Selected box size width int BoxHeight; /// Selected box size height + int NumDirections; /// Number of directions unit can face int MinAttackRange; /// Minimal attack range int _AttackRange; /// How far can the unit attack int ReactRangeComputer; /// Reacts on enemy for computer @@ -636,7 +641,7 @@ extern Animations* AnimationsByIdent(const char* ident); extern void SaveUnitTypes(FILE* file); /// Save the unit-type table extern UnitType* NewUnitTypeSlot(char*);/// Allocate an empty unit-type slot /// Draw the sprite frame of unit-type -extern void DrawUnitType(const UnitType* type,unsigned frame,int x,int y); +extern void DrawUnitType(const UnitType* type,int frame,int x,int y); extern void InitUnitTypes(void); /// Init unit-type table extern void LoadUnitTypes(void); /// Load the unit-type data diff --git a/src/stratagus/missile.cpp b/src/stratagus/missile.cpp index 3c8bb5d26..1a0ad7eb7 100644 --- a/src/stratagus/missile.cpp +++ b/src/stratagus/missile.cpp @@ -761,11 +761,11 @@ global int CheckMissileToBeDrawn(const Missile* missile) /** ** Draw missile. */ -global void DrawMissile(const MissileType* mtype,unsigned frame,int x,int y) +local void DrawMissile(const MissileType* mtype,int frame,int x,int y) { // FIXME: This is a hack for mirrored sprites - if( frame&128 ) { - VideoDrawClipX(mtype->Sprite,frame&127,x,y); + if( frame<0 ) { + VideoDrawClipX(mtype->Sprite,-frame,x,y); } else { VideoDrawClip(mtype->Sprite,frame,x,y); } @@ -845,18 +845,21 @@ global void DrawMissiles(void) local void MissileNewHeadingFromXY(Missile* missile,int dx,int dy) { int dir; + int nextdir; - // FIXME: depends on the missile directions wc 8, sc 32 - missile->SpriteFrame&=127; - missile->SpriteFrame/=5; - missile->SpriteFrame*=5; + if( missile->SpriteFrame<0 ) { + missile->SpriteFrame=-missile->SpriteFrame; + } + missile->SpriteFrame/=missile->Type->NumDirections/2+1; + missile->SpriteFrame*=missile->Type->NumDirections/2+1; - dir=((DirectionToHeading(dx,dy)+NextDirection/2)&0xFF)/NextDirection; - if( dir<=LookingS/NextDirection ) { // north->east->south + nextdir=256/missile->Type->NumDirections; + dir=((DirectionToHeading(dx,dy)+nextdir/2)&0xFF)/nextdir; + if( dir<=LookingS/nextdir ) { // north->east->south missile->SpriteFrame+=dir; } else { - // Note: 128 is the flag for flip graphic in X. - missile->SpriteFrame+=128+256/NextDirection-dir; + missile->SpriteFrame+=256/nextdir-dir; + missile->SpriteFrame=-missile->SpriteFrame; } } diff --git a/src/stratagus/script_missile.cpp b/src/stratagus/script_missile.cpp index 6eb88f832..212a79f16 100644 --- a/src/stratagus/script_missile.cpp +++ b/src/stratagus/script_missile.cpp @@ -80,6 +80,7 @@ local SCM CclDefineMissileType(SCM list) mtype=NewMissileTypeSlot(str); // str consumed! } + mtype->NumDirections=8; // // Parse the arguments, already the new tagged format. // @@ -96,6 +97,8 @@ local SCM CclDefineMissileType(SCM list) mtype->Height=gh_scm2int(gh_car(value)); } else if( gh_eq_p(value,gh_symbol2scm("frames")) ) { mtype->SpriteFrames=gh_scm2int(gh_car(list)); + } else if( gh_eq_p(value,gh_symbol2scm("num-directions")) ) { + mtype->NumDirections=gh_scm2int(gh_car(list)); } else if( gh_eq_p(value,gh_symbol2scm("fired-sound")) ) { free(mtype->FiredSound.Name); mtype->FiredSound.Name=gh_scm2newstr(gh_car(list),NULL); diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp index 532b49713..fc346105f 100644 --- a/src/unit/script_unit.cpp +++ b/src/unit/script_unit.cpp @@ -498,16 +498,16 @@ local SCM CclUnit(SCM list) unit->Frame=gh_scm2int(gh_car(list)); list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("flipped-frame")) ) { - unit->Frame=128|gh_scm2int(gh_car(list)); + unit->Frame=-gh_scm2int(gh_car(list)); list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("seen")) ) { unit->SeenFrame=gh_scm2int(gh_car(list)); list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("flipped-seen")) ) { - unit->SeenFrame=128|gh_scm2int(gh_car(list)); + unit->SeenFrame=-gh_scm2int(gh_car(list)); list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("not-seen")) ) { - unit->SeenFrame=-1; + unit->SeenFrame=UnitNotSeen; } else if( gh_eq_p(value,gh_symbol2scm("direction")) ) { unit->Direction=gh_scm2int(gh_car(list)); list=gh_cdr(list); diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp index 144ce7116..f11d50051 100644 --- a/src/unit/script_unittype.cpp +++ b/src/unit/script_unittype.cpp @@ -84,11 +84,12 @@ local SCM CclDefineUnitType(SCM list) if( type ) { DebugLevel0Fn("Redefining unit-type `%s'\n" _C_ str); free(str); - // FIXME: loose memory, old content isn't freed. + // FIXME: lose memory, old content isn't freed. } else { type=NewUnitTypeSlot(str); } + type->NumDirections=8; // // Parse the list: (still everything could be changed!) // @@ -189,6 +190,9 @@ local SCM CclDefineUnitType(SCM list) list=gh_cdr(list); type->BoxWidth=gh_scm2int(gh_car(sublist)); type->BoxHeight=gh_scm2int(gh_cadr(sublist)); + } else if( gh_eq_p(value,gh_symbol2scm("num-directions")) ) { + type->NumDirections=gh_scm2int(gh_car(list)); + list=gh_cdr(list); } else if( gh_eq_p(value,gh_symbol2scm("sight-range")) ) { type->_SightRange=gh_scm2int(gh_car(list)); list=gh_cdr(list); diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp index c9419b943..36fd99759 100644 --- a/src/unit/unit.cpp +++ b/src/unit/unit.cpp @@ -266,7 +266,7 @@ global void InitUnit(Unit* unit, UnitType* type) // Initialise unit structure (must be zero filled!) // unit->Type = type; - unit->SeenFrame = 0xFF; // Unit isn't yet seen + unit->SeenFrame = UnitNotSeen; // Unit isn't yet seen // FIXME: this is not needed for load+save, must move to other place if (1) { // Call CCL for name generation @@ -543,7 +543,7 @@ global Unit* MakeUnitAndPlace(int x,int y,UnitType* type,Player* player) // fancy buildings: mirror buildings (but shadows not correct) // if ( FancyBuildings && unit->Rs > 50 ) { - unit->Frame |= 128; + unit->Frame = -unit->Frame; } } @@ -1057,7 +1057,7 @@ global int UnitKnownOnMap(const Unit* unit) for( ; h-->0; ) { for( w=w0; w-->0; ) { if( IsMapFieldVisible(x+w,y+h) - || (unit->Type->Building && unit->SeenFrame!=0xFF + || (unit->Type->Building && unit->SeenFrame!=UnitNotSeen && IsMapFieldExplored(x+w,y+h)) ) { return 1; } @@ -1131,7 +1131,7 @@ global int UnitVisibleInViewport (int v, const Unit* unit) for( ; h-->0; ) { for( w=w0; w-->0; ) { if( IsMapFieldVisible(x+w,y+h) - || (unit->Type->Building && unit->SeenFrame!=0xFF + || (unit->Type->Building && unit->SeenFrame!=UnitNotSeen && IsMapFieldExplored(x+w,y+h)) ) { return 1; } @@ -1210,7 +1210,7 @@ global int UnitVisibleOnScreen(const Unit* unit) for( ; h-->0; ) { for( w=w0; w-->0; ) { if( IsMapFieldVisible(x+w,y+h) - || (unit->Type->Building && unit->SeenFrame!=0xFF + || (unit->Type->Building && unit->SeenFrame!=UnitNotSeen && IsMapFieldExplored(x+w,y+h)) ) { return 1; } @@ -1804,17 +1804,22 @@ global int DirectionToHeading(int delta_x,int delta_y) global void UnitUpdateHeading(Unit* unit) { int dir; + int nextdir; - // FIXME: depends on the possible unit directions wc 8, sc 32 - unit->Frame&=127; - unit->Frame/=5; - unit->Frame*=5; // Remove heading, keep animation frame - dir=((unit->Direction+NextDirection/2)&0xFF)/NextDirection; - if( dir<=LookingS/NextDirection ) { // north->east->south + if( unit->Frame<0 ) { + unit->Frame=-unit->Frame; + } + unit->Frame/=unit->Type->NumDirections/2+1; + unit->Frame*=unit->Type->NumDirections/2+1; + // Remove heading, keep animation frame + + nextdir=256/unit->Type->NumDirections; + dir=((unit->Direction+nextdir/2)&0xFF)/nextdir; + if( dir<=LookingS/nextdir ) { // north->east->south unit->Frame+=dir; } else { - // Note: 128 is the flag for flip graphic in X. - unit->Frame+=128+256/NextDirection-dir; + unit->Frame+=256/nextdir-dir; + unit->Frame=-unit->Frame; } } @@ -3856,10 +3861,10 @@ global void SaveUnit(const Unit* unit,FILE* file) #endif fprintf(file,"'pixel '(%d %d) ",unit->IX,unit->IY); fprintf(file,"'%sframe %d ", - unit->Frame&128 ? "flipped-" : "" ,unit->Frame&127); - if( unit->SeenFrame!=0xFF ) { + unit->Frame<0 ? "flipped-" : "" ,unit->Frame<0?-unit->Frame:unit->Frame); + if( unit->SeenFrame!=UnitNotSeen ) { fprintf(file,"'%sseen %d ", - unit->SeenFrame&128 ? "flipped-" : "" ,unit->SeenFrame&127); + unit->SeenFrame<0 ? "flipped-" : "" ,unit->SeenFrame<0?-unit->SeenFrame:unit->SeenFrame); } else { fprintf(file,"'not-seen "); } diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp index d0491a03b..e9be8ad94 100644 --- a/src/unit/unit_draw.cpp +++ b/src/unit/unit_draw.cpp @@ -1646,7 +1646,7 @@ local void DrawBuilding(Unit* unit) frame = unit->SeenFrame = unit->Frame; } else { frame = unit->SeenFrame; - DebugCheck( frame==-1 || frame==0xFF ); + DebugCheck( frame==UnitNotSeen ); } type=unit->Type; @@ -1678,7 +1678,7 @@ local void DrawBuilding(Unit* unit) } else if( unit->Orders[0].Action==UnitActionUpgradeTo ) { // FIXME: this frame is hardcoded!!! GraphicUnitPixels(unit,unit->Orders[0].Type->Sprite); - DrawUnitType(unit->Orders[0].Type,(frame&128)+1,x,y); + DrawUnitType(unit->Orders[0].Type,frame<0?-1:1,x,y); } else { GraphicUnitPixels(unit,type->Sprite); DrawUnitType(type,frame,x,y); diff --git a/src/unit/unittype.cpp b/src/unit/unittype.cpp index f165dbaa5..e858ec5d4 100644 --- a/src/unit/unittype.cpp +++ b/src/unit/unittype.cpp @@ -1070,15 +1070,15 @@ global UnitType* NewUnitTypeSlot(char* ident) ** @todo Do screen position caculation in high level. ** Better way to handle in x mirrored sprites. */ -global void DrawUnitType(const UnitType* type,unsigned frame,int x,int y) +global void DrawUnitType(const UnitType* type,int frame,int x,int y) { // FIXME: move this calculation to high level. x-=(type->Width-type->TileWidth*TileSizeX)/2; y-=(type->Height-type->TileHeight*TileSizeY)/2; // FIXME: This is a hack for mirrored sprites - if( frame&128 ) { - VideoDrawClipX(type->Sprite,frame&127,x,y); + if( frame<0 ) { + VideoDrawClipX(type->Sprite,-frame,x,y); } else { VideoDrawClip(type->Sprite,frame,x,y); }