* Interface for damage assignment.
This commit is contained in:
jean.chalard
2009-08-31 02:00:33 +00:00
parent c9f5519ba6
commit 6dab048a9e
19 changed files with 377 additions and 213 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o objs/WResourceManager.o OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o objs/WResourceManager.o
DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS))
RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache)
+4 -8
View File
@@ -2,22 +2,18 @@
[INIT] [INIT]
COMBATATTACKERS COMBATATTACKERS
[PLAYER1] [PLAYER1]
inplay:Elite Vanguard,Rhox Pikemaster,Bog wraith inplay:Rootbreaker Wurm,Benthic Behemoth,Bog wraith
[PLAYER2] [PLAYER2]
inplay:air elemental,grizzly bears,spark elemental,drudge skeletons,vampire bats,tundra wolves,spined wurm,paladin en-vec inplay:air elemental,grizzly bears,spark elemental,drudge skeletons,vampire bats,spined wurm
[DO] [DO]
Elite Vanguard Rootbreaker Wurm
Rhox Pikemaster Benthic Behemoth
Bog wraith Bog wraith
next next
paladin en-vec
paladin en-vec
spined wurm spined wurm
spined wurm spined wurm
vampire bats vampire bats
vampire bats vampire bats
tundra wolves
tundra wolves
air elemental air elemental
air elemental air elemental
grizzly bears grizzly bears
+2 -2
View File
@@ -33,8 +33,8 @@ class Damage: public Interruptible {
Damageable * target; Damageable * target;
int damage; int damage;
void Render(); void Render();
Damage(int id, MTGCardInstance* source, Damageable * target); Damage(MTGCardInstance* source, Damageable * target);
Damage(int id, MTGCardInstance* source, Damageable * target, int damage); Damage(MTGCardInstance* source, Damageable * target, int damage);
int resolve(); int resolve();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
}; };
+18 -10
View File
@@ -1,27 +1,35 @@
#ifndef _DAMAGERDAMAGED_H_ #ifndef _DAMAGERDAMAGED_H_
#define _DAMAGERDAMAGED_H_ #define _DAMAGERDAMAGED_H_
#include "../include/MTGCardInstance.h" #include "MTGCardInstance.h"
#include "CardGui.h"
class Player; class Player;
struct DamagerDamaged { struct DamagerDamaged : TransientCardView {
MTGCardInstance* card; bool show;
Player * damageSelecter; Player * damageSelecter;
int mCount; vector<Damage> damages;
Damage * damages[10];
int damageToDeal; int damageToDeal;
int dealOneDamage(DamagerDamaged * target); void addDamage(int damage, DamagerDamaged* source);
int addDamage(int damage, DamagerDamaged * source);
int removeDamagesTo(DamagerDamaged* target); int removeDamagesTo(DamagerDamaged* target);
int removeDamagesFrom(DamagerDamaged* source); int removeDamagesFrom(DamagerDamaged* source);
void clearDamage();
int sumDamages(); int sumDamages();
int hasLethalDamage(); bool hasLethalDamage();
DamagerDamaged(MTGCardInstance* card, Player * _damageSelecter, bool _hasFocus); DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player* damageSelecter);
DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player* damageSelecter);
~DamagerDamaged(); ~DamagerDamaged();
void Render(Player * currentPlayer); void Render(CombatStep mode);
}; };
typedef DamagerDamaged DefenserDamaged;
struct AttackerDamaged : DamagerDamaged {
vector<DefenserDamaged*> blockers;
AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player* damageSelecter);
AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player* damageSelecter);
};
#endif #endif
+13 -10
View File
@@ -5,22 +5,24 @@
#include "WEvent.h" #include "WEvent.h"
#include "CardGui.h" #include "CardGui.h"
#include "MTGCardInstance.h" #include "MTGCardInstance.h"
#include "DamagerDamaged.h"
class GuiCombat : public GuiLayer class GuiCombat : public GuiLayer
{ {
protected: protected:
GameObserver* go; GameObserver* go;
TransientCardView* active, *activeAtk; DamagerDamaged* active;
JQuad* ok_quad; AttackerDamaged* activeAtk;
static JQuad* ok_quad;
Pos ok; Pos ok;
vector<MTGCardInstance*> attackers; vector<AttackerDamaged*> attackers;
TransientCardView* current; DamagerDamaged* current;
enum { BLK, ATK, OK, NONE } cursor_pos; enum { BLK, ATK, OK, NONE } cursor_pos;
CombatStep step;
vector<TransientCardView*> atkViews; void addOne(DefenserDamaged* blocker, CombatStep);
vector<TransientCardView*> blkViews; void removeOne(DefenserDamaged* blocker, CombatStep);
void reaffectDamage(AttackerDamaged* attacker, CombatStep);
void generateBlkViews(MTGCardInstance* card); void remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after);
public: public:
GuiCombat(GameObserver* go); GuiCombat(GameObserver* go);
@@ -30,7 +32,8 @@ class GuiCombat : public GuiLayer
virtual bool CheckUserInput(u32 key); virtual bool CheckUserInput(u32 key);
virtual int receiveEventPlus(WEvent* e); virtual int receiveEventPlus(WEvent* e);
virtual int receiveEventMinus(WEvent* e); virtual int receiveEventMinus(WEvent* e);
typedef vector<AttackerDamaged*>::iterator inner_iterator;
}; };
#endif // _GUICOMBAT_H_ #endif // _GUICOMBAT_H_
+1
View File
@@ -82,6 +82,7 @@ class MTGCardInstance: public MTGCard, public Damageable {
MTGCardInstance * getNextOpponent(MTGCardInstance * previous=NULL); MTGCardInstance * getNextOpponent(MTGCardInstance * previous=NULL);
MTGCardInstance * getNextDefenser(MTGCardInstance * previous=NULL); MTGCardInstance * getNextDefenser(MTGCardInstance * previous=NULL);
int nbOpponents(); int nbOpponents();
int stepPower(CombatStep step);
int afterDamage(); int afterDamage();
+1
View File
@@ -10,6 +10,7 @@ using std::list;
class Player; class Player;
typedef enum { ORDER, FIRST_STRIKE, DAMAGE } CombatStep;
class Phase{ class Phase{
public: public:
int id; int id;
+1
View File
@@ -8,6 +8,7 @@ struct Pos {
float x, y, zoom, t, alpha; float x, y, zoom, t, alpha;
Pos(float, float, float, float, float); Pos(float, float, float, float, float);
virtual void Update(float dt); virtual void Update(float dt);
void UpdateNow();
virtual void Render(); virtual void Render();
void Render(JQuad*); void Render(JQuad*);
}; };
+8 -2
View File
@@ -1,6 +1,8 @@
#ifndef _WEVENT_H_ #ifndef _WEVENT_H_
#define _WEVENT_H_ #define _WEVENT_H_
#include "PhaseRing.h"
class MTGCardInstance; class MTGCardInstance;
class MTGGameZone; class MTGGameZone;
class Damage; class Damage;
@@ -82,10 +84,14 @@ struct WEventCreatureBlockerRank : public WEventCardUpdate {
WEventCreatureBlockerRank(MTGCardInstance * card,MTGCardInstance * exchangeWith, MTGCardInstance * attacker); WEventCreatureBlockerRank(MTGCardInstance * card,MTGCardInstance * exchangeWith, MTGCardInstance * attacker);
}; };
//Event when blockers are assigned and need to be reordered //Event when a combat phase step ends
struct WEventBlockersAssigned : public WEvent { struct WEventCombatStepChange : public WEvent
{
CombatStep step;
WEventCombatStepChange(CombatStep);
}; };
//Event when a mana is engaged //Event when a mana is engaged
//color : color //color : color
struct WEventEngageMana : public WEvent { struct WEventEngageMana : public WEvent {
-2
View File
@@ -1,8 +1,6 @@
#include "../include/config.h" #include "../include/config.h"
#include "../include/AIPlayer.h" #include "../include/AIPlayer.h"
#include "../include/CardDescriptor.h" #include "../include/CardDescriptor.h"
#include "../include/DamageResolverLayer.h"
#include "../include/DamagerDamaged.h"
#include "../include/AIStats.h" #include "../include/AIStats.h"
#include "../include/AllAbilities.h" #include "../include/AllAbilities.h"
#include "../include/ExtraCost.h" #include "../include/ExtraCost.h"
+1 -1
View File
@@ -345,7 +345,7 @@ int ActionStack::addDraw(Player * player, int nb_cards){
} }
int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){ int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){
Damage * damage = NEW Damage(mCount, _source, _target, _damage); Damage * damage = NEW Damage(_source, _target, _damage);
addAction(damage); addAction(damage);
return 1; return 1;
} }
+6 -6
View File
@@ -6,11 +6,11 @@
#include "../include/Translate.h" #include "../include/Translate.h"
#include "../include/TexturesCache.h" #include "../include/TexturesCache.h"
Damage::Damage(int id, MTGCardInstance * source, Damageable * target) { Damage::Damage(MTGCardInstance * source, Damageable * target) {
init(source, target, source->getPower()); init(source, target, source->getPower());
} }
Damage::Damage(int id, MTGCardInstance * source, Damageable * target, int damage) { Damage::Damage(MTGCardInstance * source, Damageable * target, int damage) {
init(source, target, damage); init(source, target, damage);
} }
@@ -114,21 +114,21 @@ int DamageStack::CombatDamages(int strike){
int nbdefensers = defensers->nbDefensers(attacker); int nbdefensers = defensers->nbDefensers(attacker);
if ((!strike && !attacker->has(Constants::FIRSTSTRIKE)) || (strike && attacker->has(Constants::FIRSTSTRIKE)) || attacker->has(Constants::DOUBLESTRIKE)){ if ((!strike && !attacker->has(Constants::FIRSTSTRIKE)) || (strike && attacker->has(Constants::FIRSTSTRIKE)) || attacker->has(Constants::DOUBLESTRIKE)){
if (nbdefensers == 0){ if (nbdefensers == 0){
Damage * damage = NEW Damage (mCount, attacker, game->opponent()); Damage * damage = NEW Damage(attacker, game->opponent());
Add(damage); Add(damage);
}else if (nbdefensers == 1){ }else if (nbdefensers == 1){
Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker)); Damage * damage = NEW Damage(attacker, defensers->getNextDefenser(NULL, attacker));
Add(damage); Add(damage);
}else{ }else{
//TODO Fetch list of defensers and allow user to choose targets //TODO Fetch list of defensers and allow user to choose targets
Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker)); Damage * damage = NEW Damage(attacker, defensers->getNextDefenser(NULL, attacker));
Add(damage); Add(damage);
} }
} }
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker); MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker);
while (defenser != NULL){ while (defenser != NULL){
if ((!strike && !defenser->has(Constants::FIRSTSTRIKE)) || (strike && defenser->has(Constants::FIRSTSTRIKE)) || defenser->has(Constants::DOUBLESTRIKE)){ if ((!strike && !defenser->has(Constants::FIRSTSTRIKE)) || (strike && defenser->has(Constants::FIRSTSTRIKE)) || defenser->has(Constants::DOUBLESTRIKE)){
Damage * damage = NEW Damage (mCount,defenser, attacker); Damage * damage = NEW Damage(defenser, attacker);
Add(damage); Add(damage);
} }
defenser = defensers->getNextDefenser(defenser, attacker); defenser = defensers->getNextDefenser(defenser, attacker);
+8 -5
View File
@@ -107,10 +107,11 @@ DamagerDamaged * DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Pla
if (item->card == card) return item; if (item->card == card) return item;
} }
// CardGui * cardg = game->mLayers->playLayer()->getByCard(card); // CardGui * cardg = game->mLayers->playLayer()->getByCard(card);
DamagerDamaged * item = NEW DamagerDamaged(card, selecter, mCount == 0); // DamagerDamaged * item = NEW DamagerDamaged(card, selecter, mCount == 0);
// Add(NEW TransientCardView(card->gui)); // Add(NEW TransientCardView(card->gui));
mCurr = 0; // mCurr = 0;
return item; // return item;
return NULL;
} }
void DamageResolverLayer::updateAllCoordinates(){ void DamageResolverLayer::updateAllCoordinates(){
@@ -303,6 +304,7 @@ int DamageResolverLayer::trampleDamage(){
int DamageResolverLayer::resolveDamages(){ int DamageResolverLayer::resolveDamages(){
trampleDamage(); trampleDamage();
/*
for (int i = 0; i < mCount ; i++){ for (int i = 0; i < mCount ; i++){
DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; DamagerDamaged * current = (DamagerDamaged *) mObjects[i];
for (int j =0; j < current->mCount ; j++){ for (int j =0; j < current->mCount ; j++){
@@ -310,6 +312,7 @@ int DamageResolverLayer::resolveDamages(){
damageStack->Add(damage); damageStack->Add(damage);
} }
} }
*/
game->mLayers->stackLayer()->addAction(damageStack); game->mLayers->stackLayer()->addAction(damageStack);
game->mLayers->stackLayer()->resolve(); //Wagic 2010 game->mLayers->stackLayer()->resolve(); //Wagic 2010
remainingDamageSteps--; remainingDamageSteps--;
@@ -525,10 +528,10 @@ void DamageResolverLayer::Render(){
mFont->DrawString(_("Current Damager:").c_str(), 10, 5); mFont->DrawString(_("Current Damager:").c_str(), 10, 5);
} }
for (int i = 0; i < mCount; i++){ for (int i = 0; i < mCount; i++){
((DamagerDamaged *)mObjects[i])->Render(currentChoosingPlayer); ((DamagerDamaged *)mObjects[i])->Render();
} }
if (mObjects[mCurr]){ if (mObjects[mCurr]){
((DamagerDamaged *)mObjects[mCurr])->Render(currentChoosingPlayer); ((DamagerDamaged *)mObjects[mCurr])->Render();
} }
+49 -59
View File
@@ -5,88 +5,74 @@
Temporary objects that store the damages dealt to/from creatures during the combat phase Temporary objects that store the damages dealt to/from creatures during the combat phase
*/ */
DamagerDamaged::DamagerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : TransientCardView(card, x, y), show(show), damageSelecter(damageSelecter) {}
DamagerDamaged::DamagerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : TransientCardView(card, ref), show(show), damageSelecter(damageSelecter) {}
DamagerDamaged::DamagerDamaged(MTGCardInstance* card, Player * _damageSelecter, bool _hasFocus) : card(card){ DamagerDamaged::~DamagerDamaged(){}
mCount = 0;
damageSelecter = _damageSelecter;
damageToDeal = card->power;
}
DamagerDamaged::~DamagerDamaged(){
for (int i = 0; i < mCount; i++){
SAFE_DELETE(damages[i]);
}
}
int DamagerDamaged::sumDamages(){ int DamagerDamaged::sumDamages(){
int total = 0; int total = 0;
for (int i = 0; i < mCount; i++){ for (vector<Damage>::iterator i = damages.begin(); i != damages.end(); ++i)
total += damages[i]->damage; total += i->damage;
}
return total; return total;
} }
int DamagerDamaged::hasLethalDamage(){ bool DamagerDamaged::hasLethalDamage(){
if (sumDamages() >= card->life) return 1; return (sumDamages() >= card->life);
return 0;
} }
int DamagerDamaged::dealOneDamage(DamagerDamaged * target){ void DamagerDamaged::addDamage(int damage, DamagerDamaged* source){
if (!damageToDeal) return 0; for (vector<Damage>::iterator i = damages.begin(); i != damages.end(); ++i)
damageToDeal--; if (i->source == source->card){
#if defined (WIN32) || defined (LINUX) i->damage += damage;
char buf[4096]; if (0 >= i->damage) damages.erase(i);
sprintf(buf, "==========\n%s can still deal %i damages\n=============\n", card->getName().c_str(), damageToDeal); return;
OutputDebugString(buf); }
#endif if (0 < damage) damages.push_back(Damage(source->card, this->card,damage));
return target->addDamage(1, this); return;
} }
int DamagerDamaged::addDamage(int damage, DamagerDamaged * source){
for (int i = 0; i < mCount; i++){
if (damages[i]->source == source->card){
damages[i]->damage+= damage;
return damage;
}
}
damages[mCount] = NEW Damage(mCount, source->card, this->card,damage);
mCount++;
return damage;
}
int DamagerDamaged::removeDamagesTo(DamagerDamaged * target){
damageToDeal+= target->removeDamagesFrom(this);
return 1;
}
int DamagerDamaged::removeDamagesFrom(DamagerDamaged* source){ int DamagerDamaged::removeDamagesFrom(DamagerDamaged* source){
for (int i = 0; i < mCount; i++){ for (vector<Damage>::iterator i = damages.begin(); i != damages.end(); ++i)
if (damages[i]->source == source->card){ if (i->source == source->card){
int damage = damages[i]->damage; int damage = i->damage;
SAFE_DELETE(damages[i]); damages.erase(i);
damages[i] = damages[mCount-1];
mCount--;
return damage; return damage;
} }
}
return 0; return 0;
} }
void DamagerDamaged::Render(Player * currentPlayer){ void DamagerDamaged::clearDamage()
{
damages.clear();
}
void DamagerDamaged::Render(CombatStep mode)
{
TransientCardView::Render();
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT);
mFont->SetBase(0); mFont->SetBase(0);
// CardGui::Render();
/* switch (mode)
char buf[4096]; {
if (currentPlayer != damageSelecter){ case ORDER :
if (hasLethalDamage()){ mFont->SetColor(ARGB(92,255,255,255));
mFont->DrawString("X",x,y); break;
case FIRST_STRIKE :
case DAMAGE :
mFont->SetColor(ARGB(255, 255, 64, 0));
break;
} }
mFont->SetColor(ARGB(255,255,0,0));
char buf[6];
// if (currentPlayer != damageSelecter){
/* if (hasLethalDamage()){
mFont->DrawString("X",x,y);
}*/
sprintf(buf, "%i", sumDamages()); sprintf(buf, "%i", sumDamages());
mFont->DrawString(buf,x+5, y+5); mFont->DrawString(buf, actX - 14 * actZ + 5, actY - 14 * actZ);
/*
}else{ }else{
mFont->SetColor(ARGB(255,0,0,255)); mFont->SetColor(ARGB(255,0,0,255));
sprintf(buf, "%i", damageToDeal); sprintf(buf, "%i", damageToDeal);
@@ -95,3 +81,7 @@ void DamagerDamaged::Render(Player * currentPlayer){
mFont->SetColor(ARGB(255,255,255,255)); mFont->SetColor(ARGB(255,255,255,255));
*/ */
} }
AttackerDamaged::AttackerDamaged(MTGCardInstance* card, float x, float y, bool show, Player * damageSelecter) : DamagerDamaged(card, x, y, show, damageSelecter) {}
AttackerDamaged::AttackerDamaged(MTGCardInstance* card, const Pos& ref, bool show, Player * damageSelecter) : DamagerDamaged(card, ref, show, damageSelecter) {}
+2 -2
View File
@@ -88,7 +88,7 @@ void GameObserver::nextGamePhase(){
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){
blockersAssigned = 1; blockersAssigned = 1;
receiveEvent(NEW WEventBlockersAssigned()); receiveEvent(NEW WEventCombatStepChange(ORDER));
/* /*
if (!mLayers->combatLayer()->autoOrderBlockers()){ if (!mLayers->combatLayer()->autoOrderBlockers()){
OutputDebugString("Player has To choose ordering!"); OutputDebugString("Player has To choose ordering!");
@@ -156,7 +156,7 @@ void GameObserver::userRequestNextGamePhase(){
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){
blockersAssigned = 1; blockersAssigned = 1;
receiveEvent(NEW WEventBlockersAssigned()); receiveEvent(NEW WEventCombatStepChange(ORDER));
/* /*
if (!mLayers->combatLayer()->autoOrderBlockers()){ if (!mLayers->combatLayer()->autoOrderBlockers()){
OutputDebugString("Player has To choose ordering!"); OutputDebugString("Player has To choose ordering!");
+226 -87
View File
@@ -4,15 +4,18 @@
#include "Closest.cpp" #include "Closest.cpp"
static const float MARGIN = 70; static const float MARGIN = 70;
static const float TOP_LINE = 80;
struct Left : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test)
{ return ref->y == test->y && ref->x > test->x && test->show; } };
struct Right : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test)
{ return ref->y == test->y && ref->x < test->x && test->show; } };
struct Left : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test) JQuad* GuiCombat::ok_quad = NULL;
{ return ref->y == test->y && ref->x > test->x; } };
struct Right : public Exp { static inline bool test(CardSelector::Target* ref, CardSelector::Target* test)
{ return ref->y == test->y && ref->x < test->x; } };
GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), activeAtk(NULL), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), cursor_pos(NONE), step(DAMAGE)
GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), cursor_pos(NONE) {
if (NULL == ok_quad)
{ {
if (!GameApp::CommonRes->GetTexture("Ok.png")) if (!GameApp::CommonRes->GetTexture("Ok.png"))
{ {
@@ -20,67 +23,118 @@ GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), ok(S
GameApp::CommonRes->CreateQuad("OK", "Ok.png", 0, 0, 56, 45); GameApp::CommonRes->CreateQuad("OK", "Ok.png", 0, 0, 56, 45);
} }
ok_quad = GameApp::CommonRes->GetQuad("OK"); ok_quad = GameApp::CommonRes->GetQuad("OK");
if(ok_quad)
ok_quad->SetHotSpot(28, 22); ok_quad->SetHotSpot(28, 22);
} }
}
GuiCombat::~GuiCombat() GuiCombat::~GuiCombat()
{ {
} }
void GuiCombat::Update(float dt) template <typename T>
static inline void repos(typename vector<T*>::iterator begin, typename vector<T*>::iterator end, signed size = -1)
{ {
if (NONE != cursor_pos) for (typename vector<T*>::iterator it = begin; it != end; ++it)
{ if ((*it)->show) ++size;
for (vector<TransientCardView*>::iterator it = atkViews.begin(); it != atkViews.end(); ++it) float space = (SCREEN_WIDTH - 2*MARGIN) / size;
(*it)->Update(dt);
for (vector<TransientCardView*>::iterator it = blkViews.begin(); it != blkViews.end(); ++it)
(*it)->Update(dt);
ok.Update(dt);
}
}
void GuiCombat::generateBlkViews(MTGCardInstance* card)
{
for (vector<TransientCardView*>::iterator it = blkViews.begin(); it != blkViews.end(); ++it)
SAFE_DELETE(*it);
blkViews.clear();
if (card && card->blockers.size() > 0)
{
float space = (SCREEN_WIDTH - 2*MARGIN) / card->blockers.size();
float pos = MARGIN; float pos = MARGIN;
for (list<MTGCardInstance*>::iterator it = card->blockers.begin(); it != card->blockers.end(); ++it) for (typename vector<T*>::iterator it = begin; it != end; ++it)
if ((*it)->show)
{ {
TransientCardView* t = NEW TransientCardView(*it, 20, 60); (*it)->x = pos;
blkViews.push_back(t);
t->x = pos; t->y = 60;
t->zoom = 2.2; t->t = 0;
pos += space; pos += space;
} }
} }
void GuiCombat::Update(float dt)
{
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
(*it)->Update(dt);
if (activeAtk)
for (vector<DefenserDamaged*>::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q)
(*q)->Update(dt);
ok.Update(dt);
}
void GuiCombat::remaskBlkViews(AttackerDamaged* before, AttackerDamaged* after)
{
if (after)
{
for (vector<DefenserDamaged*>::iterator q = after->blockers.begin(); q != after->blockers.end(); ++q)
{
(*q)->actX = MARGIN; (*q)->y = TOP_LINE;
(*q)->zoom = 2.2; (*q)->t = 0;
}
repos<DefenserDamaged>(after->blockers.begin(), after->blockers.end());
}
}
void GuiCombat::reaffectDamage(AttackerDamaged* attacker, CombatStep step)
{
attacker->clearDamage();
unsigned damage = attacker->card->stepPower(step);
for (vector<DefenserDamaged*>::iterator it = attacker->blockers.begin(); it != attacker->blockers.end(); ++it)
{
(*it)->clearDamage();
unsigned actual_damage = MIN(damage, (unsigned)MAX((*it)->card->toughness, 0));
(*it)->addDamage(actual_damage, attacker);
attacker->addDamage((*it)->card->stepPower(step), *it);
damage -= actual_damage;
}
}
void GuiCombat::addOne(DefenserDamaged* blocker, CombatStep step)
{
blocker->addDamage(1, activeAtk);
signed damage = activeAtk->card->stepPower(step);
for (vector<DamagerDamaged*>::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it)
{
damage -= (*it)->sumDamages();
if (0 > damage) { (*it)->addDamage(-1, activeAtk); break; }
}
}
void GuiCombat::removeOne(DefenserDamaged* blocker, CombatStep step)
{
blocker->addDamage(-1, activeAtk);
for (vector<DamagerDamaged*>::iterator it = activeAtk->blockers.begin(); it != activeAtk->blockers.end(); ++it)
if (!(*it)->hasLethalDamage()) { (*it)->addDamage(1, activeAtk); break; }
} }
bool GuiCombat::CheckUserInput(u32 key) bool GuiCombat::CheckUserInput(u32 key)
{ {
if (NONE == cursor_pos) return false; if (NONE == cursor_pos) return false;
TransientCardView* oldActive = active; DamagerDamaged* oldActive = active;
switch (key) switch (key)
{ {
case PSP_CTRL_CIRCLE: case PSP_CTRL_CIRCLE:
if (BLK == cursor_pos) if (BLK == cursor_pos)
activeAtk->card->raiseBlockerRankOrder(active->card); if (ORDER == step) { activeAtk->card->raiseBlockerRankOrder(active->card); }
else if (OK == cursor_pos) { cursor_pos = NONE; go->userRequestNextGamePhase(); }; else
break;
case PSP_CTRL_UP:
if (ATK == cursor_pos)
{ {
activeAtk = active; signed damage = activeAtk->card->stepPower(step);
active = blkViews.front(); for (vector<DamagerDamaged*>::iterator it = activeAtk->blockers.begin(); *it != active; ++it)
damage -= (*it)->sumDamages();
signed now = active->sumDamages();
damage -= now;
if (damage > 0) addOne(active, step);
else
for (now -= active->card->toughness; now >= 0; --now) removeOne(active, step);
}
else if (ATK == cursor_pos)
{
active = activeAtk->blockers.front();
active->zoom = 2.7; active->zoom = 2.7;
cursor_pos = BLK; cursor_pos = BLK;
} }
return true; else if (OK == cursor_pos)
case PSP_CTRL_DOWN: switch (step)
{
case ORDER : go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); break;
case FIRST_STRIKE : go->receiveEvent(NEW WEventCombatStepChange(DAMAGE)); break;
case DAMAGE : cursor_pos = NONE; go->userRequestNextGamePhase(); break;
}
break;
case PSP_CTRL_TRIANGLE:
if (BLK == cursor_pos) if (BLK == cursor_pos)
{ {
oldActive->zoom = 2.2; oldActive->zoom = 2.2;
@@ -92,9 +146,13 @@ bool GuiCombat::CheckUserInput(u32 key)
switch (cursor_pos) switch (cursor_pos)
{ {
case NONE : break; case NONE : break;
case OK : active = atkViews.back(); cursor_pos = ATK; break; case OK :
case ATK : active = closest<Left>(atkViews, NULL, active); break; for (vector<AttackerDamaged*>::reverse_iterator it = attackers.rbegin(); it != attackers.rend(); ++it) if ((*it)->show) { active = *it; break; }
case BLK : active = closest<Left>(blkViews, NULL, active); break; activeAtk = static_cast<AttackerDamaged*>(active);
cursor_pos = ATK;
break;
case ATK : active = closest<Left>(attackers, NULL, static_cast<AttackerDamaged*>(active)); activeAtk = static_cast<AttackerDamaged*>(active); break;
case BLK : active = closest<Left>(activeAtk->blockers, NULL, static_cast<DefenserDamaged*>(active)); break;
} }
break; break;
case PSP_CTRL_RIGHT: case PSP_CTRL_RIGHT:
@@ -102,22 +160,31 @@ bool GuiCombat::CheckUserInput(u32 key)
{ {
case NONE : case NONE :
case OK : break; case OK : break;
case BLK : active = closest<Right>(blkViews, NULL, active); break; case BLK : active = closest<Right>(activeAtk->blockers, NULL, static_cast<DefenserDamaged*>(active)); break;
case ATK : active = closest<Right>(atkViews, NULL, active); case ATK : active = closest<Right>(attackers, NULL, static_cast<AttackerDamaged*>(active));
if (active == oldActive) { active = NULL; cursor_pos = OK; } if (active == oldActive) { active = activeAtk = NULL; cursor_pos = OK; }
else activeAtk = static_cast<AttackerDamaged*>(active);
break; break;
} }
break; break;
case PSP_CTRL_DOWN:
if (ORDER == step || BLK != cursor_pos || active->sumDamages() <= 0) break;
removeOne(active, step);
break;
case PSP_CTRL_UP:
if (ORDER == step || BLK != cursor_pos) break;
addOne(active, step);
break;
case PSP_CTRL_SQUARE: case PSP_CTRL_SQUARE:
case PSP_CTRL_RTRIGGER: case PSP_CTRL_RTRIGGER:
active = NULL; cursor_pos = OK; active = activeAtk = NULL; cursor_pos = OK;
break; break;
} }
if (oldActive != active) if (oldActive != active)
{ {
if (oldActive) oldActive->zoom = 2.2; if (oldActive && oldActive != activeAtk) oldActive->zoom = 2.2;
if (active) active->zoom = 2.7; if (active) active->zoom = 2.7;
if (ATK == cursor_pos) generateBlkViews(active->card); if (ATK == cursor_pos) remaskBlkViews(dynamic_cast<AttackerDamaged*>(oldActive), static_cast<AttackerDamaged*>(active));
} }
if (OK == cursor_pos) ok.zoom = 1.5; else ok.zoom = 1.0; if (OK == cursor_pos) ok.zoom = 1.5; else ok.zoom = 1.0;
return true; return true;
@@ -129,15 +196,19 @@ void GuiCombat::Render()
JRenderer* renderer = JRenderer::GetInstance(); JRenderer* renderer = JRenderer::GetInstance();
renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0));
for (vector<TransientCardView*>::iterator it = atkViews.begin(); it != atkViews.end(); ++it) for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
(*it)->Render(); if ((*it)->show) (*it)->Render(step);
for (vector<TransientCardView*>::iterator it = blkViews.begin(); it != blkViews.end(); ++it) if (activeAtk)
(*it)->Render(); for (vector<DefenserDamaged*>::iterator q = activeAtk->blockers.begin(); q != activeAtk->blockers.end(); ++q)
(*q)->Render(step);
if(ok_quad) if (ok_quad) ok.Render(ok_quad);
ok.Render(ok_quad);
renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0)); renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0));
if (FIRST_STRIKE == step)
{
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT);
mFont->SetColor(ARGB(255, 64, 255, 64));
mFont->DrawString("First strike damage", 370, 2);
}
} }
int GuiCombat::receiveEventPlus(WEvent* e) int GuiCombat::receiveEventPlus(WEvent* e)
@@ -146,65 +217,133 @@ int GuiCombat::receiveEventPlus(WEvent* e)
{ {
if (NULL == event->after) return 0; if (NULL == event->after) return 0;
cout << "Attacker : " << event->card->name << " " << event->before << " -> " << event->after << endl; cout << "Attacker : " << event->card->name << " " << event->before << " -> " << event->after << endl;
attackers.push_back(event->card); AttackerDamaged* t = NEW AttackerDamaged(event->card, *(event->card->view), true, NULL);
attackers.push_back(t);
return 1; return 1;
} }
else if (WEventCreatureBlocker* event = dynamic_cast<WEventCreatureBlocker*>(e)) else if (WEventCreatureBlocker* event = dynamic_cast<WEventCreatureBlocker*>(e))
{ {
cout << "Blocker : " << event->card->name << " " << event->before << " -> " << event->after << endl; cout << "Blocker : " << event->card->name << " " << event->before << " -> " << event->after << endl;
if (NULL == event->after) return 0; for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
if ((*it)->card == event->after)
{
DefenserDamaged* t = NEW DefenserDamaged(event->card, *(event->card->view), true, NULL);
t->y = t->actY = TOP_LINE; t->actT = t->t = 0; t->actZ = t->zoom = 2.2;
(*it)->blockers.push_back(t);
return 1; return 1;
} }
return 0;
}
else if (WEventCreatureBlockerRank* event = dynamic_cast<WEventCreatureBlockerRank*>(e)) else if (WEventCreatureBlockerRank* event = dynamic_cast<WEventCreatureBlockerRank*>(e))
{ {
cout << "Order : " << event->card->name << " -> " << event->exchangeWith->name << endl; cout << "Order : " << event->card->name << " -> " << event->exchangeWith->name << endl;
vector<TransientCardView*>::iterator it1, it2; for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
for (it1 = blkViews.begin(); it1 != blkViews.end(); ++it1) if ((*it1)->card == event->card) break; if (blkViews.end() == it1) return 1; if ((*it)->card == event->attacker)
for (it2 = blkViews.begin(); it2 != blkViews.end(); ++it2) if ((*it2)->card == event->exchangeWith) break; if (blkViews.end() == it2) return 1; {
vector<DefenserDamaged*>::iterator it1, it2;
for (it1 = (*it)->blockers.begin(); it1 != (*it)->blockers.end(); ++it1) if ((*it1)->card == event->card) break;
if ((*it)->blockers.end() == it1) return 1;
for (it2 = (*it)->blockers.begin(); it2 != (*it)->blockers.end(); ++it2) if ((*it2)->card == event->exchangeWith) break;
if ((*it)->blockers.end() == it2) return 1;
float x = (*it1)->x; float x = (*it1)->x;
(*it1)->x = (*it2)->x; (*it1)->x = (*it2)->x;
(*it2)->x = x; (*it2)->x = x;
std::iter_swap(it1, it2);
reaffectDamage(*it, DAMAGE);
}
return 1; return 1;
} }
return 0; return 0;
} }
int GuiCombat::receiveEventMinus(WEvent* e) int GuiCombat::receiveEventMinus(WEvent* e)
{ {
// (WEventZoneChange* event = dynamic_cast<WEventZoneChange*>(e)
if (WEventCreatureAttacker* event = dynamic_cast<WEventCreatureAttacker*>(e)) if (WEventCreatureAttacker* event = dynamic_cast<WEventCreatureAttacker*>(e))
{ {
if (NULL == event->before) return 0; if (NULL == event->before) return 0;
for (vector<MTGCardInstance*>::iterator it = attackers.begin(); it != attackers.end(); ++it) for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
if (*it == event->card) if ((*it)->card == event->card)
{ {
attackers.erase(it); attackers.erase(it);
return 1; return 1;
} }
return 1; return 1;
} }
else if (WEventBlockersAssigned* event = dynamic_cast<WEventBlockersAssigned*>(e)) else if (WEventCreatureBlocker* event = dynamic_cast<WEventCreatureBlocker*>(e))
{ {
if (active) return 0; // Why do I take this event twice >.> cout << "Blocker : " << event->card->name << " " << event->before << " -> " << event->after << endl;
if (go->currentPlayer->isAI()) return 0; for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
unsigned size = 0; if ((*it)->card == event->before)
for (vector<MTGCardInstance*>::iterator it = attackers.begin(); it != attackers.end(); ++it) for (vector<DefenserDamaged*>::iterator q = (*it)->blockers.begin(); q != (*it)->blockers.end(); ++q)
if (1 < (*it)->blockers.size()) ++size; if ((*q)->card == event->card)
if (0 == size) return 1;
float space = (SCREEN_WIDTH - 2*MARGIN) / size;
float pos = MARGIN;
for (vector<MTGCardInstance*>::iterator it = attackers.begin(); it != attackers.end(); ++it)
if (1 < (*it)->blockers.size())
{ {
TransientCardView* t = NEW TransientCardView(*it, *(*it)->view); DefenserDamaged* d = *q;
atkViews.push_back(t); (*it)->blockers.erase(q);
t->x = pos; t->y = 210; SAFE_DELETE(d);
t->zoom = 2.2; t->t = 0; return 1;
pos += space; }
} return 0;
active = *atkViews.begin(); }
active->zoom = 2.7; else if (WEventCombatStepChange* event = dynamic_cast<WEventCombatStepChange*>(e))
generateBlkViews(active->card); switch (event->step)
cursor_pos = ATK; {
case ORDER:
{
if (ORDER == step) return 0; // Why do I take this twice ? >.>
if (go->currentPlayer->isAI()) { go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE)); return 1; }
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
{
(*it)->show = (1 < (*it)->blockers.size());
reaffectDamage(*it, DAMAGE);
}
active = NULL;
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
if ((*it)->show)
{
(*it)->y = 210;
(*it)->zoom = 2.2; (*it)->t = 0;
if (!active) active = *it;
}
repos<AttackerDamaged>(attackers.begin(), attackers.end(), 0);
if (active)
{
active->zoom = 2.7; // We know there is at least one, so this cannot be NULL
activeAtk = static_cast<AttackerDamaged*>(active);
remaskBlkViews(NULL, static_cast<AttackerDamaged*>(active));
cursor_pos = ATK;
step = ORDER;
}
else
go->receiveEvent(NEW WEventCombatStepChange(FIRST_STRIKE));
return 1;
}
case FIRST_STRIKE:
for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker)
if ((*attacker)->card->has(Constants::FIRSTSTRIKE) || (*attacker)->card->has(Constants::DOUBLESTRIKE)) goto DAMAGE;
go->receiveEvent(NEW WEventCombatStepChange(DAMAGE));
return 1;
case DAMAGE: DAMAGE:
if (go->currentPlayer->isAI()) { go->userRequestNextGamePhase(); return 1; }
step = event->step;
cursor_pos = ATK;
for (inner_iterator attacker = attackers.begin(); attacker != attackers.end(); ++attacker)
reaffectDamage(*attacker, step);
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
(*it)->show = ((*it)->card->has(Constants::DOUBLESTRIKE) || ((*it)->card->has(Constants::FIRSTSTRIKE) ^ (DAMAGE == step))) && (1 < (*it)->blockers.size());
repos<AttackerDamaged>(attackers.begin(), attackers.end(), 0);
active = NULL;
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) if ((*it)->show) { active = *it; break; }
if (active)
{
active->zoom = 2.7;
activeAtk = static_cast<AttackerDamaged*>(active);
remaskBlkViews(NULL, static_cast<AttackerDamaged*>(active));
}
else
{
if (FIRST_STRIKE == step) go->receiveEvent(NEW WEventCombatStepChange(DAMAGE));
else go->userRequestNextGamePhase();
}
return 1;
} }
return 0; return 0;
} }
+12
View File
@@ -630,3 +630,15 @@ JSample * MTGCardInstance::getSample(){
return NULL; return NULL;
} }
int MTGCardInstance::stepPower(CombatStep step)
{
switch (step)
{
case FIRST_STRIKE :
if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE)) return MAX(0, power); else return 0;
case DAMAGE :
if (has(Constants::FIRSTSTRIKE)) return 0; else return MAX(0, power);
default : return 0;
}
}
+4
View File
@@ -11,6 +11,10 @@ void Pos::Update(float dt)
actA += 10 * dt * (alpha - actA); actA += 10 * dt * (alpha - actA);
} }
void Pos::UpdateNow()
{
actX = x; actY = y; actT = t; actZ = zoom; actA = alpha;
}
void Pos::Render(){} void Pos::Render(){}
void Pos::Render(JQuad* quad) void Pos::Render(JQuad* quad)
{ {
+2
View File
@@ -25,3 +25,5 @@ WEventCreatureBlockerRank::WEventCreatureBlockerRank(MTGCardInstance * card, MTG
WEventEngageMana::WEventEngageMana(int color, MTGCardInstance* card, ManaPool * destination) : WEvent(), color(color), card(card), destination(destination) {} WEventEngageMana::WEventEngageMana(int color, MTGCardInstance* card, ManaPool * destination) : WEvent(), color(color), card(card), destination(destination) {}
WEventConsumeMana::WEventConsumeMana(int color, ManaPool * source) : WEvent(), color(color),source(source) {} WEventConsumeMana::WEventConsumeMana(int color, ManaPool * source) : WEvent(), color(color),source(source) {}
WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source) : WEvent(), source(source){} WEventEmptyManaPool::WEventEmptyManaPool(ManaPool * source) : WEvent(), source(source){}
WEventCombatStepChange::WEventCombatStepChange(CombatStep step) : WEvent(), step(step) {};