1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

battle and general upgrades and bugfixes

This commit is contained in:
mateuszb 2008-04-07 17:51:46 +00:00
parent 36779118b5
commit 149c6772e2
13 changed files with 218 additions and 37 deletions

View File

@ -22,8 +22,10 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
{
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(b->second.position, b->second.owner == attackingHeroInstance->tempOwner);
creAnims[b->second.ID] = (new CCreatureAnimation(b->second.creature->animDefName));
creAnims[b->second.ID]->setType(2);
creAnims[b->second.ID]->pos = genRect(creAnims[b->second.ID]->fullHeight, creAnims[b->second.ID]->fullWidth, coords.first, coords.second);
}
//preparing menu background and terrain
std::vector< std::string > & backref = CGI->mh->battleBacks[ LOCPLINT->cb->battleGetBattlefieldType() ];
@ -206,8 +208,7 @@ void CBattleInterface::show(SDL_Surface * to)
//showing units //a lot of work...
for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
{
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(stacks[j->first].position, stacks[j->first].owner == attackingHeroInstance->tempOwner);
j->second->nextFrame(to, coords.first, coords.second, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0, j->first==activeStack);
j->second->nextFrame(to, j->second->pos.x, j->second->pos.y, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0 || j->second->getType()==0, j->first==activeStack); //increment always when moving
}
//units shown
@ -251,6 +252,10 @@ void CBattleInterface::bWaitf()
void CBattleInterface::bDefencef()
{
BattleAction * ba = new BattleAction;
ba->actionType = 3;
ba->stackNumber = activeStack;
LOCPLINT->cb->battleMakeAction(ba);
}
void CBattleInterface::bConsoleUpf()
@ -282,14 +287,62 @@ void CBattleInterface::stackActivated(int number)
void CBattleInterface::stackMoved(int number, int destHex)
{
int curStackPos = LOCPLINT->cb->battleGetPos(number);
for(int i=0; i<6; ++i)
int steps = 6;
int hexWbase = 44, hexHbase = 42;
creAnims[number]->setType(0);
for(int i=0; i<steps; ++i)
{
//creAnims[number]->setType(0);
switch(CBattleHex::mutualPosition(curStackPos, destHex))
{
case 0:
creAnims[number]->pos.x -= hexWbase/(2*steps);
creAnims[number]->pos.y -= hexHbase/steps;
break;
case 1:
creAnims[number]->pos.x += hexWbase/(2*steps);
creAnims[number]->pos.y -= hexHbase/steps;
break;
case 2:
creAnims[number]->pos.x += hexWbase/steps;
break;
case 3:
creAnims[number]->pos.x += hexWbase/(2*steps);
creAnims[number]->pos.y += hexHbase/steps;
break;
case 4:
creAnims[number]->pos.x -= hexWbase/(2*steps);
creAnims[number]->pos.y += hexHbase/steps;
break;
case 5:
creAnims[number]->pos.x -= hexWbase/steps;
break;
}
show();
SDL_framerateDelay(LOCPLINT->mainFPSmng);
}
creAnims[number]->setType(2); //resetting to delault
CStack curs = LOCPLINT->cb->battleGetStackByID(number);
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, curs.owner == attackingHeroInstance->tempOwner);
creAnims[number]->pos.x = coords.first;
creAnims[number]->pos.y = coords.second;
}
void CBattleInterface::stackAttacking(int ID, int dest)
{
}
void CBattleInterface::hexLclicked(int whichOne)
{
if(!LOCPLINT->cb->battleIsStackMine(LOCPLINT->cb->battleGetStack(whichOne))) //if player is trying to attack eney unit
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = 6;
ba->destinationTile = whichOne;
ba->stackNumber = activeStack;
LOCPLINT->cb->battleMakeAction(ba);
}
if((whichOne%17)!=0 && (whichOne%17)!=16)
{
LOCPLINT->cb->battleMoveCreature(activeStack, whichOne);
@ -385,6 +438,23 @@ std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker)
return ret;
}
signed char CBattleHex::mutualPosition(int hex1, int hex2)
{
if(hex2 == hex1 - ( (hex1/17)%2 ? 18 : 17 )) //top left
return 0;
if(hex2 == hex1 - ( (hex1/17)%2 ? 17 : 16 )) //top right
return 1;
if(hex2 == hex1 - 1 && hex1%17 != 0) //left
return 5;
if(hex2 == hex1 + 1 && hex1%17 != 16) //right
return 2;
if(hex2 == hex1 + ( (hex1/17)%2 ? 16 : 17 )) //bottom left
return 4;
if(hex2 == hex1 + ( (hex1/17)%2 ? 17 : 18 )) //bottom right
return 3;
return -1;
}
void CBattleHex::activate()
{
Hoverable::activate();

View File

@ -33,6 +33,7 @@ public:
bool hovered, strictHovered;
CBattleInterface * myInterface; //interface that owns me
static std::pair<int, int> getXYUnitAnim(int hexNum, bool attacker); //returns (x, y) of left top corner of animation
static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
//for user interactions
void hover (bool on);
void activate();
@ -86,13 +87,14 @@ public:
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
void activate();
void deactivate();
void show(SDL_Surface * to);
void show(SDL_Surface * to = NULL);
//call-ins
void newStack(CStack stack); //new stack appeared on battlefield
void stackRemoved(CStack stack); //stack disappeared from batlefiled
void stackActivated(int number); //active stack has been changed
void stackMoved(int number, int destHex); //stack with id number moved to destHex
void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
void turnEnded(); //caled when current unit cannot get new orders
void hexLclicked(int whichOne); //hex only call-in
};

View File

@ -558,6 +558,26 @@ int CCallback::battleGetBattlefieldType()
return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].terType;
}
int CCallback::battleGetStack(int pos)
{
for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
{
if(CGI->state->curB->stacks[g]->position == pos)
return CGI->state->curB->stacks[g]->ID;
}
return -1;
}
CStack CCallback::battleGetStackByID(int ID)
{
for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
{
if(CGI->state->curB->stacks[g]->ID == ID)
return *(CGI->state->curB->stacks[g]);
}
return CStack();
}
int CCallback::battleGetPos(int stack)
{
for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
@ -565,6 +585,20 @@ int CCallback::battleGetPos(int stack)
if(CGI->state->curB->stacks[g]->ID == stack)
return CGI->state->curB->stacks[g]->position;
}
return -1;
}
int CCallback::battleMakeAction(BattleAction* action)
{
switch(action->actionType)
{
case 3: //defend
return battleMoveCreature(action->stackNumber, battleGetPos(action->stackNumber));
case 6: //move or attack
return battleMoveCreature(action->stackNumber, action->destinationTile);
}
delete action;
return -1; //error
}
std::map<int, CStack> CCallback::battleGetStacks()
@ -584,6 +618,7 @@ CCreature CCallback::battleGetCreature(int number)
if(CGI->state->curB->stacks[h]->ID == number) //creature found
return *(CGI->state->curB->stacks[h]->creature);
}
return CCreature();
}
bool CCallback::battleMoveCreature(int ID, int dest)
@ -600,6 +635,16 @@ std::vector<int> CCallback::battleGetAvailableHexes(int ID)
return CGI->state->battleGetRange(ID);
}
bool CCallback::battleIsStackMine(int ID)
{
for(int h=0; h<CGI->state->curB->stacks.size(); ++h)
{
if(CGI->state->curB->stacks[h]->ID == ID) //creature found
return CGI->state->curB->stacks[h]->owner == player;
}
return false;
}
int3 CScriptCallback::getPos(CGObjectInstance * ob)
{
return ob->pos;

View File

@ -97,12 +97,14 @@ public:
int battleGetBattlefieldType(); // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
int battleGetObstaclesAtTile(int tile); //returns bitfield
int battleGetStack(int pos); //returns ID of stack on the tile
CStack battleGetStackByID(int ID); //returns stack info by given ID
int battleGetPos(int stack); //returns position (tile ID) of stack
int battleMakeAction(BattleAction* action);//perform action with an active stack (or custom action)
std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
CCreature battleGetCreature(int number); //returns type of creature by given number of stack
bool battleMoveCreature(int ID, int dest); //moves creature with id ID to dest if possible
std::vector<int> battleGetAvailableHexes(int ID); //reutrns numbers of hexes reachable by creature with id ID
bool battleIsStackMine(int ID); //returns true if stack with id ID belongs to caller
//friends

View File

@ -11,6 +11,7 @@
#include <sstream>
#include "CMessage.h"
#include "hch/CGeneralTextHandler.h"
#include "CCallback.h"
extern TTF_Font * GEOR16;
CBuildingRect::CBuildingRect(Structure *Str)
:str(Str), moi(false)

View File

@ -1,14 +1,22 @@
#ifndef CGAMEINTERFACE_H
#define CGAMEINTERFACE_H
#include "global.h"
#include "CCallback.h"
//#include "CCallback.h"
#include <vector>
BOOST_TRIBOOL_THIRD_STATE(outOfRange)
using namespace boost::logic;
class CCallback;
class ICallback;
class CGlobalAI;
class CGHeroInstance;
class CSelectableComponent;
struct HeroMoveDetails;
class CGHeroInstance;
class CGTownInstance;
class CGObjectInstance;
class CCreatureSet;
class CObstacle
{
int ID;

View File

@ -215,6 +215,24 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
//first checks
if(curB->stackActionPerformed) //because unit cannot be moved more than once
return false;
bool stackAtEnd = false; //true if there is a stack at the end of the path (we should attack it)
unsigned char owner = -1; //owner moved of unit
for(int g=0; g<curB->stacks.size(); ++g)
{
if(curB->stacks[g]->position == dest)
{
stackAtEnd = true;
break;
}
}
for(int g=0; g<curB->stacks.size(); ++g)
{
if(curB->stacks[g]->ID == ID)
{
owner = curB->stacks[g]->owner;
break;
}
}
//selecting moved stack
CStack * curStack = NULL;
for(int y=0; y<curB->stacks.size(); ++y)
@ -233,7 +251,8 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
accessibility[k] = true;
for(int g=0; g<curB->stacks.size(); ++g)
{
accessibility[curB->stacks[g]->position] = false;
if(curB->stacks[g]->owner == owner) //we don't want to lock enemy's positions
accessibility[curB->stacks[g]->position] = false;
}
int predecessor[187]; //for getting the Path
for(int b=0; b<187; ++b)
@ -305,8 +324,15 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
}
for(int v=path.size()-1; v>=0; --v)
{
LOCPLINT->battleStackMoved(ID, path[v]);
curStack->position = path[v];
if(v!=0 || !stackAtEnd) //it's not the last step
{
LOCPLINT->battleStackMoved(ID, path[v]);
curStack->position = path[v];
}
else //if it's last step and we should attack unit at the end
{
LOCPLINT->battleStackAttacking(ID, path[v]);
}
}
curB->stackActionPerformed = true;
LOCPLINT->actionFinished(BattleAction());
@ -317,12 +343,14 @@ std::vector<int> CGameState::battleGetRange(int ID)
{
int initialPlace=-1; //position of unit
int radius=-1; //range of unit
unsigned char owner = -1; //owner of unit
for(int g=0; g<curB->stacks.size(); ++g)
{
if(curB->stacks[g]->ID == ID)
{
initialPlace = curB->stacks[g]->position;
radius = curB->stacks[g]->creature->speed;
owner = curB->stacks[g]->owner;
break;
}
}
@ -332,7 +360,8 @@ std::vector<int> CGameState::battleGetRange(int ID)
accessibility[k] = true;
for(int g=0; g<curB->stacks.size(); ++g)
{
accessibility[curB->stacks[g]->position] = false;
if(curB->stacks[g]->owner == owner) //we don't want to lock enemy's positions
accessibility[curB->stacks[g]->position] = false;
}

View File

@ -9,7 +9,9 @@
#include "CAdvmapInterface.h"
#include "hch\CLodHandler.h"
#include "AdventureMapButton.h"
#include "hch\CObjectHandler.h"
#include "CMessage.h"
#include "CCallback.h"
#include <sstream>
extern SDL_Surface * screen;

View File

@ -1948,6 +1948,11 @@ void CPlayerInterface::battleStackMoved(int ID, int dest)
dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest);
}
void CPlayerInterface::battleStackAttacking(int ID, int dest)
{
dynamic_cast<CBattleInterface*>(curint)->stackAttacking(ID, dest);
}
void CPlayerInterface::showComp(SComponent comp)
{
adventureInt->infoBar.showComp(&comp,4000);

View File

@ -1,8 +1,10 @@
#pragma once
#ifndef CPLAYERINTERFACE_H
#define CPLAYERINTERFACE_H
#include "global.h"
#include "CGameInterface.h"
#include "SDL.h"
#include "SDL_framerate.h"
#include <map>
class CDefEssential;
template <typename T> class AdventureMapButton;
class CDefHandler;
@ -12,7 +14,16 @@ class CGHeroInstance;
class CAdvMapInt;
class CCastleInterface;
class CStack;
class SComponent;
class CCreature;
struct SDL_Surface;
class CPath;
class CCreatureAnimation;
class CSelectableComponent;
class CCreatureSet;
class CGObjectInstance;
template<typename T>class CSlider;
class IShowable
{
public:
@ -76,7 +87,7 @@ public:
bool pressedL;
ClickableL();
virtual ~ClickableL(){};
virtual void clickLeft (tribool down)=0;
virtual void clickLeft (boost::logic::tribool down)=0;
virtual void activate()=0;
virtual void deactivate()=0;
};
@ -86,7 +97,7 @@ public:
bool pressedR;
ClickableR();
virtual ~ClickableR(){};
virtual void clickRight (tribool down)=0;
virtual void clickRight (boost::logic::tribool down)=0;
virtual void activate()=0;
virtual void deactivate()=0;
};
@ -133,9 +144,9 @@ public:
int3 posr; //position in the bitmap
int state;
T* delg;
void(T::*func)(tribool);
CSCButton(CDefHandler * img, CIntObject * obj, void(T::*poin)(tribool), T* Delg=NULL);
void clickLeft (tribool down);
void(T::*func)(boost::logic::tribool);
CSCButton(CDefHandler * img, CIntObject * obj, void(T::*poin)(boost::logic::tribool), T* Delg=NULL);
void clickLeft (boost::logic::tribool down);
void activate();
void deactivate();
void show(SDL_Surface * to = NULL);
@ -146,7 +157,7 @@ class CInfoWindow : public CSimpleWindow //text + comp. + ok button
public:
CSCButton<CInfoWindow> okb;
std::vector<SComponent*> components;
virtual void okClicked(tribool down);
virtual void okClicked(boost::logic::tribool down);
virtual void close();
CInfoWindow();
virtual ~CInfoWindow();
@ -155,7 +166,7 @@ class CSelWindow : public CInfoWindow //component selection window
{ //uwaga - to okno nie usuwa swoich komponentow przy usuwaniu, moga sie one jeszcze przydac skryptowi - tak wiec skrypt korzystajacyz tego okna musi je usunac
public:
void selectionChange(CSelectableComponent * to);
void okClicked(tribool down);
void okClicked(boost::logic::tribool down);
void close();
CSelWindow(){};
};
@ -166,7 +177,7 @@ public:
virtual void activate();
virtual void deactivate();
virtual void close()=0;
void clickRight (tribool down);
void clickRight (boost::logic::tribool down);
virtual ~CRClickPopup(){};
};
@ -198,7 +209,7 @@ public:
SComponent(Etype Type, int Subtype, int Val);
//SComponent(const & SComponent r);
void clickRight (tribool down);
void clickRight (boost::logic::tribool down);
virtual SDL_Surface * getImg();
virtual void activate();
virtual void deactivate();
@ -214,7 +225,7 @@ public:
CSelWindow * owner;
void clickLeft(tribool down);
void clickLeft(boost::logic::tribool down);
CSelectableComponent(Etype Type, int Sub, int Val, CSelWindow * Owner=NULL, SDL_Surface * Border=NULL);
~CSelectableComponent();
void activate();
@ -232,8 +243,8 @@ public:
int upg; //0 - up garrison, 1 - down garrison
virtual void hover (bool on);
void clickRight (tribool down);
void clickLeft(tribool down);
void clickRight (boost::logic::tribool down);
void clickLeft(boost::logic::tribool down);
void activate();
void deactivate();
void show();
@ -314,7 +325,7 @@ public:
void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
//battles
void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::logic::tribool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
void actionStarted(BattleAction action);//occurs BEFORE every action taken by any stack or by the hero
@ -322,6 +333,7 @@ public:
void activeStack(int stackID); //called when it's turn of that stack
void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner);
void battleStackMoved(int ID, int dest);
void battleStackAttacking(int ID, int dest);
//-------------//
@ -374,10 +386,10 @@ public:
int selected, //id of selected position, <0 if none
from;
const int SIZE;
tribool pressed; //true=up; false=down; indeterminate=none
boost::logic::tribool pressed; //true=up; false=down; indeterminate=none
CList(int Size = 5);
void clickLeft(tribool down);
void clickLeft(boost::logic::tribool down);
void activate();
void deactivate();
virtual void mouseMoved (SDL_MouseMotionEvent & sEvent)=0;
@ -397,8 +409,8 @@ public:
void genList();
void select(int which);
void mouseMoved (SDL_MouseMotionEvent & sEvent);
void clickLeft(tribool down);
void clickRight(tribool down);
void clickLeft(boost::logic::tribool down);
void clickRight(boost::logic::tribool down);
void hover (bool on);
void keyPressed (SDL_KeyboardEvent & key);
void updateHList();
@ -422,8 +434,8 @@ public:
void genList();
void select(int which);
void mouseMoved (SDL_MouseMotionEvent & sEvent);
void clickLeft(tribool down);
void clickRight(tribool down);
void clickLeft(boost::logic::tribool down);
void clickRight(boost::logic::tribool down);
void hover (bool on);
void keyPressed (SDL_KeyboardEvent & key);
void draw();
@ -449,10 +461,12 @@ public:
void Buy();
void Cancel();
void sliderMoved(int to);
void clickLeft(tribool down);
void clickLeft(boost::logic::tribool down);
void activate();
void deactivate();
void show(SDL_Surface * to = NULL);
CRecrutationWindow(std::vector<std::pair<int,int> > & Creatures); //creatures - pairs<creature_ID,amount>
~CRecrutationWindow();
};
};
#endif //CPLAYERINTERFACE_H

View File

@ -18,7 +18,7 @@ Names_of_Units_DEFS_in_order_of_ID
16 CDWARF.DEF
17 CBDWAR.DEF
18 CELF.DEF
19 CGELF.DEF
19 CGRELF.DEF
20 CPEGAS.DEF
21 CAPEGS.DEF
22 CTREE.DEF

View File

@ -666,6 +666,8 @@ CCreatureAnimation::CCreatureAnimation(std::string name) : RLEntries(NULL), RWEn
{
//load main file
std::string data2 = CGI->spriteh->getTextFile(name);
if(data2.size()==0)
throw new std::string("no such def!");
FDef = new unsigned char[data2.size()];
for(int g=0; g<data2.size(); ++g)
{

View File

@ -1,6 +1,7 @@
#ifndef CCREATUREHANDLER_H
#define CCREATUREHANDLER_H
#include "CPlayerInterface.h"
#include <string>
#include <vector>
#include <map>
@ -8,7 +9,6 @@
class CDefHandler;
struct SDL_Surface;
//#include "CDefHandler.h"
class CCreature
{
@ -66,10 +66,10 @@ public:
void loadUnitAnimations();
};
class CCreatureAnimation
class CCreatureAnimation : public CIntObject
{
private:
int totalEntries, DEFType, totalBlocks, fullWidth, fullHeight;
int totalEntries, DEFType, totalBlocks;
bool allowRepaint;
int length;
BMPPalette palette[256];
@ -94,6 +94,7 @@ private:
unsigned int frames; //number of frames
int type; //type of animation being displayed (-1 - whole animation, >0 - specified part [default: -1])
public:
int fullWidth, fullHeight; //read-only, please!
CCreatureAnimation(std::string name); //c-tor
~CCreatureAnimation(); //d-tor //not necessery ATM