This commit is contained in:
@@ -0,0 +1,624 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/AIPlayer.h"
|
||||
#include "../include/CardDescriptor.h"
|
||||
#include "../include/DamageResolverLayer.h"
|
||||
#include "../include/DamagerDamaged.h"
|
||||
#include "../include/AIStats.h"
|
||||
|
||||
const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"};
|
||||
|
||||
AIPlayer::AIPlayer(MTGPlayerCards * _deck, char * file): Player(_deck, file){
|
||||
potentialMana = NEW ManaCost();
|
||||
nextCardToPlay = NULL;
|
||||
stats = NULL;
|
||||
}
|
||||
|
||||
AIPlayer::~AIPlayer(){
|
||||
if (potentialMana) delete potentialMana;
|
||||
SAFE_DELETE(stats);
|
||||
}
|
||||
MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random){
|
||||
for (int i = 0; i < game->hand->nb_cards; i++){
|
||||
MTGCardInstance * card = game->hand->cards[i];
|
||||
if (!tc->alreadyHasTarget(card) && tc->canTarget(card)){
|
||||
return card;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int AIPlayer::Act(){
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
if (gameObs->currentPlayer == this){
|
||||
gameObs->userRequestNextGamePhase();
|
||||
return 1;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("tapping land for mana\n");
|
||||
#endif
|
||||
|
||||
ManaCost * diff = potentialMana->Diff(cost);
|
||||
int currentCost = 0;
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
CardDescriptor cd;
|
||||
cd.setColor(MTG_COLOR_LAND);
|
||||
cd.tapped = -1;
|
||||
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Found mana card\n");
|
||||
#endif
|
||||
int doTap = 1;
|
||||
for (int i=MTG_NB_COLORS-1; i>= 0; i--){
|
||||
if (diff->getCost(i) && card->hasSubtype(MTG_LAND_TEXTS[i]) ){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Not Gonna Tap\n");
|
||||
#endif
|
||||
diff->remove(i,1);
|
||||
doTap = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (doTap){
|
||||
gameObs->cardClick(card);
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Tapped\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
delete(diff);
|
||||
|
||||
/*
|
||||
|
||||
for (int i=MTG_NB_COLORS-1; i>= 0; i--){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf,"Testing %s \n" ,MTG_LAND_TEXTS[i]);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
currentCost = cost->getCost(i);
|
||||
while(currentCost){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
sprintf(buf,"Cost for %s is %i \n" ,MTG_LAND_TEXTS[i], currentCost);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
MTGCardInstance * card = NULL;
|
||||
while(currentCost && (card = cd.nextmatch(game->inPlay, card))){
|
||||
if (i==MTG_COLOR_ARTIFACT || card->hasSubtype(MTG_LAND_TEXTS[i]) ){
|
||||
currentCost--;
|
||||
gameObs->cardClick(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("ok land tapped");
|
||||
#endif
|
||||
}
|
||||
//TODO a better function that does not take into account only basic lands
|
||||
ManaCost * AIPlayer::getPotentialMana(){
|
||||
SAFE_DELETE(potentialMana);
|
||||
potentialMana = NEW ManaCost();
|
||||
CardDescriptor cd;
|
||||
cd.setColor(MTG_COLOR_LAND);
|
||||
cd.tapped = -1;
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
|
||||
if (card->hasSubtype("plains")){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Found Potential plain\n");
|
||||
#endif
|
||||
potentialMana->add(MTG_COLOR_WHITE,1);
|
||||
}else if(card->hasSubtype("swamp")){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Found Potential swamp\n");
|
||||
#endif
|
||||
potentialMana->add(MTG_COLOR_BLACK,1);
|
||||
}else if(card->hasSubtype("forest")){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Found Potential forestn\n");
|
||||
#endif
|
||||
potentialMana->add(MTG_COLOR_GREEN,1);
|
||||
}else if(card->hasSubtype("mountain")){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Found Potential Mountain\n");
|
||||
#endif
|
||||
potentialMana->add(MTG_COLOR_RED,1);
|
||||
}else if(card->hasSubtype("island")){
|
||||
potentialMana->add(MTG_COLOR_BLUE,1);
|
||||
}else{
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("WTF ????\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return potentialMana;
|
||||
}
|
||||
|
||||
|
||||
//Default AI does not interrupt
|
||||
int AIPlayer::checkInterrupt(){
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
if (gameObs->mLayers->stackLayer()->askIfWishesToInterrupt == this){
|
||||
gameObs->mLayers->stackLayer()->cancelInterruptOffer();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AIPlayer::effectBadOrGood(MTGCardInstance * card){
|
||||
int id = card->getMTGId();
|
||||
switch (id){
|
||||
default:
|
||||
break;
|
||||
}
|
||||
AbilityFactory * af = NEW AbilityFactory();
|
||||
int autoGuess = af->magicText(id,NULL,card);
|
||||
delete af;
|
||||
if (autoGuess) return autoGuess;
|
||||
return BAKA_EFFECT_BAD;
|
||||
}
|
||||
|
||||
int AIPlayer::chooseTarget(TargetChooser * tc){
|
||||
Targetable * potentialTargets[50];
|
||||
int nbtargets = 0;
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
int checkOnly = 0;
|
||||
if (tc){
|
||||
checkOnly = 1;
|
||||
}else{
|
||||
tc = gameObs->getCurrentTargetChooser();
|
||||
}
|
||||
if (!tc) return 0;
|
||||
if (!(gameObs->currentlyActing() == this)) return 0;
|
||||
Player * target = this;
|
||||
int cardEffect = effectBadOrGood(tc->source);
|
||||
if (cardEffect == BAKA_EFFECT_BAD){
|
||||
target = this->opponent();
|
||||
}
|
||||
|
||||
|
||||
if (!tc->alreadyHasTarget(target) && tc->canTarget(target) && nbtargets < 50){
|
||||
for (int i = 0; i < 3; i++){ //Increase probability to target a player when this is possible
|
||||
potentialTargets[nbtargets] = target;
|
||||
nbtargets++;
|
||||
}
|
||||
if (checkOnly) return 1;
|
||||
}
|
||||
MTGPlayerCards * playerZones = target->game;
|
||||
MTGGameZone * zones[] = {playerZones->hand,playerZones->library,playerZones->inPlay, playerZones->graveyard};
|
||||
for (int j = 0; j < 4; j++){
|
||||
MTGGameZone * zone = zones[j];
|
||||
for (int k=0; k< zone->nb_cards; k++){
|
||||
MTGCardInstance * card = zone->cards[k];
|
||||
if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50){
|
||||
if (checkOnly) return 1;
|
||||
int multiplier = 1;
|
||||
if (getStats() && getStats()->isInTop(card,10)){
|
||||
multiplier++;
|
||||
if (getStats()->isInTop(card,5)){
|
||||
multiplier++;
|
||||
if (getStats()->isInTop(card,3)){
|
||||
multiplier++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int l=0; l < multiplier; l++){
|
||||
potentialTargets[nbtargets] = card;
|
||||
nbtargets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nbtargets){
|
||||
int i = rand() % nbtargets;
|
||||
int type = potentialTargets[i]->typeAsTarget();
|
||||
switch(type){
|
||||
case TARGET_CARD:
|
||||
{
|
||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||
gameObs->cardClick(card);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case TARGET_PLAYER:
|
||||
{
|
||||
Player * player = ((Player *) potentialTargets[i]);
|
||||
gameObs->cardClick(NULL, player);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//BIG PROBLEM
|
||||
gameObs->cancelCurrentAction();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AIPlayer::getCreaturesInfo(Player * player, int neededInfo , int untapMode, int canAttack){
|
||||
int result = 0;
|
||||
CardDescriptor cd;
|
||||
cd.init();
|
||||
cd.setType("Creature");
|
||||
cd.tapped = untapMode;
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(player->game->inPlay, card))){
|
||||
if (!canAttack || card->canAttack()){
|
||||
if (neededInfo == INFO_NBCREATURES){
|
||||
result++;
|
||||
}else{
|
||||
result+=card->power;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AIPlayer::chooseAttackers(){
|
||||
//Attack with all creatures
|
||||
//How much damage can the other player do during his next Attack ?
|
||||
int opponentForce = getCreaturesInfo(opponent(),INFO_CREATURESPOWER);
|
||||
int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES);
|
||||
int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER,-1,1);
|
||||
int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1,1);
|
||||
bool attack = (myCreatures > opponentCreatures || myForce > opponentForce || myForce > 2*opponent()->life);
|
||||
if (attack){
|
||||
CardDescriptor cd;
|
||||
cd.init();
|
||||
cd.setType("Creature");
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AIPlayer::chooseBlockers(){
|
||||
map<MTGCardInstance *, int> opponentsToughness;
|
||||
int opponentForce = getCreaturesInfo(opponent(),INFO_CREATURESPOWER);
|
||||
int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1);
|
||||
int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER);
|
||||
int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1);
|
||||
CardDescriptor cd;
|
||||
cd.init();
|
||||
cd.setType("Creature");
|
||||
cd.tapped = -1;
|
||||
MTGCardInstance * card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
int set = 0;
|
||||
while(!set){
|
||||
if (!card->defenser){
|
||||
set = 1;
|
||||
}else{
|
||||
MTGCardInstance * attacker = card->defenser;
|
||||
map<MTGCardInstance *,int>::iterator it = opponentsToughness.find(attacker);
|
||||
if ( it == opponentsToughness.end()){
|
||||
opponentsToughness[attacker] = attacker->toughness;
|
||||
it = opponentsToughness.find(attacker);
|
||||
}
|
||||
if (opponentsToughness[attacker] > 0 && getStats() && getStats()->isInTop(attacker,3,false)){
|
||||
opponentsToughness[attacker]-= card->power;
|
||||
set = 1;
|
||||
}else{
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
if (card->defenser && opponentsToughness[card->defenser] > 0){
|
||||
while (card->defenser) GameObserver::GetInstance()->cardClick(card);
|
||||
}
|
||||
}
|
||||
card = NULL;
|
||||
while((card = cd.nextmatch(game->inPlay, card))){
|
||||
if(!card->defenser){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
int set = 0;
|
||||
while(!set){
|
||||
if (!card->defenser){
|
||||
set = 1;
|
||||
}else{
|
||||
MTGCardInstance * attacker = card->defenser;
|
||||
if (opponentsToughness[attacker] <= 0 || (card->toughness <= card->defenser->power && opponentForce*2 <life) || card->defenser->nbOpponents()>1){
|
||||
GameObserver::GetInstance()->cardClick(card);
|
||||
}else{
|
||||
set = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AIPlayer::combatDamages(){
|
||||
int result = 0;
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
Player * currentPlayer = gameObs->currentPlayer;
|
||||
int currentGamePhase = gameObs->getCurrentGamePhase();
|
||||
if (currentGamePhase != MTG_PHASE_COMBATDAMAGE) return 0;
|
||||
DamageResolverLayer * drl = gameObs->mLayers->combatLayer();
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("AI Combat Phase START\n");
|
||||
#endif
|
||||
if (drl->currentChoosingPlayer == this){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("This player chooses\n");
|
||||
#endif
|
||||
for (int i = 0; i < drl->mCount; i++){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("AI Combat Phase\n");
|
||||
#endif
|
||||
DamagerDamaged * current = (DamagerDamaged *) drl->mObjects[i];
|
||||
if (current->damageSelecter == this){
|
||||
result = 1;
|
||||
DamagerDamaged * canardEmissaire = NULL;
|
||||
for (int j = 0; j < drl->mCount; j++){
|
||||
DamagerDamaged * opponent = (DamagerDamaged *) drl->mObjects[j];
|
||||
if (drl->isOpponent(current, opponent)){
|
||||
if (!canardEmissaire) canardEmissaire = opponent;
|
||||
int over = opponent->hasLethalDamage();
|
||||
while(!over){
|
||||
if(!current->dealOneDamage(opponent)){
|
||||
over = 1;
|
||||
}else{
|
||||
over = opponent->hasLethalDamage();
|
||||
}
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "==========\n%s deals %i damages to %s\n=============\n", current->card->getName(), 1, opponent->card->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canardEmissaire && !current->card->has(TRAMPLE)){
|
||||
while(current->dealOneDamage(canardEmissaire)){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("==========\nDealing damage to Canard Emissaire\n================\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result){
|
||||
drl->nextPlayer();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
AIStats * AIPlayer::getStats(){
|
||||
if (!stats){
|
||||
char statFile[512];
|
||||
sprintf(statFile, "Res/ai/baka/stats/%s.stats", opponent()->deckFile.c_str());
|
||||
stats = new AIStats(this, statFile);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, MTGPlayerCards * oponents_deck){
|
||||
int nbdecks = 0;
|
||||
int found = 1;
|
||||
while (found){
|
||||
found = 0;
|
||||
char buffer[512];
|
||||
sprintf(buffer, "Res/ai/baka/deck%i.txt",nbdecks+1);
|
||||
std::ifstream file(buffer);
|
||||
if(file){
|
||||
found = 1;
|
||||
file.close();
|
||||
nbdecks++;
|
||||
}
|
||||
}
|
||||
if (!nbdecks) return NULL;
|
||||
int deckid = 1 + rand() % (nbdecks);
|
||||
char deckFile[512];
|
||||
sprintf(deckFile, "Res/ai/baka/deck%i.txt",deckid);
|
||||
char deckFileSmall[512];
|
||||
sprintf(deckFileSmall, "ai_baka_deck%i",deckid);
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char debuf[4096];
|
||||
sprintf(debuf,"Deck File: %s", deckFile);
|
||||
OutputDebugString(debuf);
|
||||
#endif
|
||||
int deck_cards_ids[100];
|
||||
int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
|
||||
MTGPlayerCards * deck = NEW MTGPlayerCards(collection,deck_cards_ids, nb_elements);
|
||||
AIPlayerBaka * baka = NEW AIPlayerBaka(deck,deckFileSmall);
|
||||
return baka;
|
||||
}
|
||||
|
||||
|
||||
MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const char * type){
|
||||
int maxCost = -1;
|
||||
MTGCardInstance * nextCardToPlay = NULL;
|
||||
MTGCardInstance * card = NULL;
|
||||
CardDescriptor cd;
|
||||
cd.init();
|
||||
cd.setType(type);
|
||||
card = NULL;
|
||||
while((card = cd.nextmatch(game->hand, card))){
|
||||
int currentCost = card->getManaCost()->getConvertedCost();
|
||||
if (currentCost > maxCost && potentialMana->canAfford(card->getManaCost())){
|
||||
TargetChooserFactory * tcf = NEW TargetChooserFactory();
|
||||
TargetChooser * tc = tcf->createTargetChooser(card);
|
||||
delete tcf;
|
||||
if (tc){
|
||||
int hasTarget = (chooseTarget(tc));
|
||||
delete tc;
|
||||
if (!hasTarget)continue;
|
||||
}
|
||||
nextCardToPlay = card;
|
||||
maxCost = currentCost;
|
||||
}
|
||||
}
|
||||
return nextCardToPlay;
|
||||
}
|
||||
|
||||
AIPlayerBaka::AIPlayerBaka(MTGPlayerCards * _deck, char * file): AIPlayer(_deck,file){
|
||||
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
|
||||
if (mAvatarTex)
|
||||
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
|
||||
initTimer();
|
||||
}
|
||||
|
||||
void AIPlayerBaka::initTimer(){
|
||||
timer = 20;
|
||||
}
|
||||
|
||||
int AIPlayerBaka::Act(){
|
||||
GameObserver * gameObs = GameObserver::GetInstance();
|
||||
int currentGamePhase = gameObs->getCurrentGamePhase();
|
||||
|
||||
if (currentGamePhase == MTG_PHASE_CLEANUP && currentGamePhase != oldGamePhase){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("updating stats\n");
|
||||
#endif
|
||||
if (getStats()) getStats()->updateStats();
|
||||
}
|
||||
|
||||
|
||||
oldGamePhase = currentGamePhase;
|
||||
|
||||
if (checkInterrupt()) return 0;
|
||||
|
||||
timer--;
|
||||
if (timer>0){
|
||||
return 0;
|
||||
}
|
||||
initTimer();
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("==========\nNew Act CALL\n================\n");
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("==========\nCombat Damages ?\n================\n");
|
||||
#endif
|
||||
if (combatDamages()) return 0;
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("==========\nChoose Target ?\n================\n");
|
||||
#endif
|
||||
if (chooseTarget()) return 0;
|
||||
|
||||
|
||||
Player * currentPlayer = gameObs->currentPlayer;
|
||||
|
||||
|
||||
|
||||
|
||||
CardDescriptor cd;
|
||||
|
||||
|
||||
if (currentPlayer == this){
|
||||
MTGCardInstance * card = NULL;
|
||||
switch(currentGamePhase){
|
||||
case MTG_PHASE_FIRSTMAIN:
|
||||
case MTG_PHASE_SECONDMAIN:
|
||||
if (canPutLandsIntoPlay){
|
||||
|
||||
//Attempt to put land into play
|
||||
cd.init();
|
||||
cd.setColor(MTG_COLOR_LAND);
|
||||
card = cd.match(game->hand);
|
||||
if (card){
|
||||
gameObs->cardClick(card);
|
||||
}
|
||||
}
|
||||
if(NULL == card){
|
||||
|
||||
//Attempt to put creature into play
|
||||
if (manaPool->getConvertedCost()==0){
|
||||
|
||||
//No mana, try to get some
|
||||
getPotentialMana();
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buffe[4096];
|
||||
|
||||
sprintf(buffe,"potentail mana %i\n",potentialMana->getConvertedCost() );
|
||||
OutputDebugString(buffe);
|
||||
#endif
|
||||
if (potentialMana->getConvertedCost() > 0){
|
||||
|
||||
|
||||
//look for the most expensive creature we can afford
|
||||
nextCardToPlay = FindCardToPlay(potentialMana, "creature");
|
||||
//Let's Try an enchantment maybe ?
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "enchantment");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "artifact");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "instant");
|
||||
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(potentialMana, "sorcery");
|
||||
if (nextCardToPlay){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
sprintf(buffe, "Putting Card Into Play: %s", nextCardToPlay->getName());
|
||||
OutputDebugString(buffe);
|
||||
#endif
|
||||
|
||||
tapLandsForMana(potentialMana,nextCardToPlay->getManaCost());
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(potentialMana);
|
||||
}else{
|
||||
//We have mana, we can try to put the card into play
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Mana paid, ready to put card into play\n");
|
||||
#endif
|
||||
if (nextCardToPlay){
|
||||
gameObs->cardClick(nextCardToPlay);
|
||||
nextCardToPlay = NULL;
|
||||
}else{
|
||||
//ERROR, WE PAID MANA WITHOUT ANY WILL TO PLAY
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL == card && NULL == nextCardToPlay){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Switching to next phase\n");
|
||||
#endif
|
||||
gameObs->userRequestNextGamePhase();
|
||||
}
|
||||
break;
|
||||
case MTG_PHASE_COMBATATTACKERS:
|
||||
chooseAttackers();
|
||||
gameObs->userRequestNextGamePhase();
|
||||
break;
|
||||
default:
|
||||
gameObs->userRequestNextGamePhase();
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
switch(currentGamePhase){
|
||||
case MTG_PHASE_COMBATBLOCKERS:
|
||||
chooseBlockers();
|
||||
gameObs->userRequestNextGamePhase();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/AIStats.h"
|
||||
#include "../include/GameObserver.h"
|
||||
#include "../include/Player.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
|
||||
bool compare_aistats(AIStat * first, AIStat * second){
|
||||
float damage1 = first->value / first->occurences;
|
||||
float damage2 = second->value/ second->occurences;
|
||||
return (damage1 > damage2);
|
||||
}
|
||||
|
||||
AIStats::AIStats(Player * _player, char * _filename){
|
||||
filename = _filename;
|
||||
load(_filename);
|
||||
player = _player;
|
||||
}
|
||||
|
||||
AIStats::~AIStats(){
|
||||
list<AIStat *>::iterator it;
|
||||
for ( it=stats.begin() ; it != stats.end(); it++ ){
|
||||
AIStat * stat = *it;
|
||||
delete stat;
|
||||
}
|
||||
}
|
||||
|
||||
void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier){
|
||||
MTGCard * card = cardInstance->model;
|
||||
AIStat * stat = find(card);
|
||||
if (!stat){
|
||||
stat = NEW AIStat(card->getMTGId(),0,1,0);
|
||||
stats.push_back(stat);
|
||||
}
|
||||
if (damage->target == player){
|
||||
stat->value+= multiplier * STATS_PLAYER_MULTIPLIER * damage->damage;
|
||||
}else if (damage->target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
|
||||
MTGCardInstance * target = (MTGCardInstance *)damage->target;
|
||||
if (target->controller() == player && !target->isInPlay()){
|
||||
//One of my creatures got lethal damage...
|
||||
stat->value+= multiplier * STATS_CREATURE_MULTIPLIER * damage->damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AIStats::updateStats(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
ActionStack * as = game->mLayers->stackLayer();
|
||||
Damage * damage = ((Damage * )as->getNext(NULL,ACTION_DAMAGE, RESOLVED_OK));
|
||||
MTGGameZone * opponentZone = player->opponent()->game->inPlay;
|
||||
while(damage){
|
||||
MTGCardInstance * card = damage->source;
|
||||
updateStatsCard(card,damage);
|
||||
|
||||
//Auras on damage source can be the cause
|
||||
for (int i=0; i < opponentZone->nb_cards; i++){
|
||||
MTGCardInstance * aura = opponentZone->cards[i];
|
||||
if (aura->target == card){
|
||||
updateStatsCard(aura,damage, STATS_AURA_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
damage = ((Damage * )as->getNext(damage,ACTION_DAMAGE, RESOLVED_OK));
|
||||
}
|
||||
stats.sort(compare_aistats);
|
||||
save();
|
||||
}
|
||||
|
||||
bool AIStats::isInTop(MTGCardInstance * card,int max, bool tooSmallCountsForTrue ){
|
||||
if (stats.size()<max) return tooSmallCountsForTrue;
|
||||
int n = 0;
|
||||
MTGCard * source = card->model;
|
||||
int id = source->getMTGId();
|
||||
list<AIStat *>::iterator it;
|
||||
for ( it=stats.begin() ; it != stats.end(); it++ ){
|
||||
if (n >= max) return false;
|
||||
AIStat * stat = *it;
|
||||
if (stat->source == id){
|
||||
if (stat->value>=0) return true;
|
||||
return false;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AIStat * AIStats::find(MTGCard * source){
|
||||
int id = source->getMTGId();
|
||||
list<AIStat *>::iterator it;
|
||||
for ( it=stats.begin() ; it != stats.end(); it++ ){
|
||||
AIStat * stat = *it;
|
||||
if (stat->source == id) return stat;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AIStats::load(char * filename){
|
||||
std::ifstream file(filename);
|
||||
std::string s;
|
||||
|
||||
if(file){
|
||||
while(std::getline(file,s)){
|
||||
int cardid = atoi(s.c_str());
|
||||
std::getline(file,s);
|
||||
int value = atoi(s.c_str());
|
||||
std::getline(file,s);
|
||||
int direct = atoi(s.c_str());
|
||||
AIStat * stat = NEW AIStat(cardid,value,1,direct);
|
||||
stats.push_back(stat);
|
||||
}
|
||||
file.close();
|
||||
}else{
|
||||
//TODO Error management
|
||||
}
|
||||
}
|
||||
void AIStats::save(){
|
||||
std::ofstream file(filename.c_str());
|
||||
char writer[128];
|
||||
if (file){
|
||||
list<AIStat *>::iterator it;
|
||||
for ( it=stats.begin() ; it != stats.end(); it++ ){
|
||||
AIStat * stat = *it;
|
||||
if (stat->value > 0){
|
||||
sprintf(writer,"%i\n%i\n%i\n", stat->source,stat->value/2,stat->direct);
|
||||
file<<writer;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "../include/ActionElement.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/Targetable.h"
|
||||
#include "../include/TargetChooser.h"
|
||||
|
||||
ActionElement::ActionElement(int id):JGuiObject(id){
|
||||
activeState = INACTIVE;
|
||||
modal = 0;
|
||||
waitingForAnswer = 0;
|
||||
currentPhase = -1;
|
||||
newPhase = -1;
|
||||
tc = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
void ActionElement::RenderMessageBackground(float y0, int _height){
|
||||
float height = _height;
|
||||
PIXEL_TYPE colors_up[] =
|
||||
{
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(128,255,255,255)
|
||||
};
|
||||
|
||||
PIXEL_TYPE colors_down[] =
|
||||
{
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(0,255,255,255)
|
||||
};
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(0,y0,SCREEN_WIDTH,height/2,colors_up);
|
||||
renderer->FillRect(0,y0+height/2,SCREEN_WIDTH,height/2,colors_down);
|
||||
// mEngine->DrawLine(0,y0,SCREEN_WIDTH,y0,ARGB(128,255,255,255));
|
||||
// mEngine->DrawLine(0,y0+height,SCREEN_WIDTH,y0+height,ARGB(128,255,255,255));
|
||||
}*/
|
||||
|
||||
int ActionElement::getActivity(){
|
||||
|
||||
return activeState;
|
||||
}
|
||||
|
||||
|
||||
int ActionElement::isReactingToTargetClick(Targetable * object){
|
||||
if (object && object->typeAsTarget() == TARGET_CARD) return isReactingToClick((MTGCardInstance *)object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActionElement::reactToTargetClick(Targetable * object){
|
||||
if (object->typeAsTarget() == TARGET_CARD) return reactToClick((MTGCardInstance *)object);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/ActionLayer.h"
|
||||
#include "../include/GameObserver.h"
|
||||
#include "../include/Targetable.h"
|
||||
|
||||
int ActionLayer::unstopableRenderInProgress(){
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if (currentAction->getActivity() > 0){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ActionLayer::CheckUserInput(float dt){
|
||||
if (menuObject){
|
||||
abilitiesMenu->Update(dt);
|
||||
return;
|
||||
}
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
currentAction->CheckUserInput(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ActionLayer::Update(float dt){
|
||||
if (menuObject){
|
||||
return;
|
||||
}
|
||||
modal = 0;
|
||||
for (int i=mCount -1 ;i>=0;i--){
|
||||
if (mObjects[i]!= NULL){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if (currentAction->testDestroy()){
|
||||
currentAction->destroy();
|
||||
Remove(currentAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
int newPhase = GameObserver::GetInstance()->getCurrentGamePhase();
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
currentAction->newPhase = newPhase;
|
||||
currentAction->Update(dt);
|
||||
currentAction->currentPhase = newPhase;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ActionLayer::Render (){
|
||||
if (menuObject){
|
||||
abilitiesMenu->Render();
|
||||
return;
|
||||
}
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
//if (currentAction->getActivity() > 0){
|
||||
currentAction->Render();
|
||||
//return;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TargetChooser * ActionLayer::getCurrentTargetChooser(){
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if(currentAction->waitingForAnswer) return currentAction->tc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ActionLayer::isWaitingForAnswer(){
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if(currentAction->waitingForAnswer) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActionLayer::isReactingToTargetClick(Targetable * card){
|
||||
int result = 0;
|
||||
|
||||
if (isWaitingForAnswer()) return -1;
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
result += currentAction->isReactingToTargetClick(card);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ActionLayer::reactToTargetClick(Targetable * card){
|
||||
int result = 0;
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if(currentAction->waitingForAnswer){
|
||||
return currentAction->reactToTargetClick(card);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
result += currentAction->reactToTargetClick(card);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//TODO Simplify with only object !!!
|
||||
int ActionLayer::isReactingToClick(MTGCardInstance * card){
|
||||
int result = 0;
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if(currentAction->waitingForAnswer) return -1;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
result += currentAction->isReactingToClick(card);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ActionLayer::reactToClick(MTGCardInstance * card){
|
||||
int result = 0;
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if(currentAction->waitingForAnswer){
|
||||
return currentAction->reactToClick(card);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
result += currentAction->reactToClick(card);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ActionLayer::isModal(){
|
||||
if (modal) return 1;
|
||||
if (menuObject) return 1;
|
||||
for (int i=0; i<mCount; i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if (currentAction->modal) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ActionLayer::setMenuObject(Targetable * object){
|
||||
menuObject = object;
|
||||
if (abilitiesMenu){
|
||||
delete abilitiesMenu;
|
||||
}
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
abilitiesMenu = NEW SimpleMenu(10, this, mFont, 100, 100, 200);
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[i];
|
||||
if (currentAction->isReactingToTargetClick(object)){
|
||||
abilitiesMenu->Add(i,currentAction->getMenuText());
|
||||
}
|
||||
}
|
||||
abilitiesMenu->Add(-1, "Cancel");
|
||||
modal = 1;
|
||||
}
|
||||
|
||||
|
||||
void ActionLayer::ButtonPressed(int controllerid, int controlid){
|
||||
if (controlid == -1){
|
||||
|
||||
}else{
|
||||
ActionElement * currentAction = (ActionElement *)mObjects[controlid];
|
||||
currentAction->reactToTargetClick(menuObject);
|
||||
}
|
||||
menuObject = 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
The Action Stack contains all information for Game Events that can be interrupted (Interruptible)
|
||||
*/
|
||||
#include "../include/debug.h"
|
||||
#include "../include/ActionStack.h"
|
||||
#include "../include/MTGAbility.h"
|
||||
#include "../include/GameObserver.h"
|
||||
#include "../include/Damage.h"
|
||||
#include "../include/ManaCost.h"
|
||||
|
||||
/*
|
||||
NextGamePhase requested by user
|
||||
*/
|
||||
|
||||
int NextGamePhase::resolve(){
|
||||
GameObserver::GetInstance()->nextGamePhase();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void NextGamePhase::Render(){
|
||||
int nextPhase = (GameObserver::GetInstance()->getCurrentGamePhase() + 1) % MTG_PHASE_CLEANUP;
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
int playerId = 1;
|
||||
if (GameObserver::GetInstance()->currentActionPlayer == GameObserver::GetInstance()->players[1]) playerId = 2;
|
||||
sprintf(buffer, "Player %i : -> %s", playerId, MTGPhaseNames[nextPhase]);
|
||||
mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT);
|
||||
}
|
||||
|
||||
NextGamePhase::NextGamePhase(int id): Interruptible(id){
|
||||
mHeight = 40;
|
||||
type = ACTION_NEXTGAMEPHASE;
|
||||
}
|
||||
|
||||
|
||||
/* Ability */
|
||||
int StackAbility::resolve(){
|
||||
return (ability->resolve());
|
||||
}
|
||||
void StackAbility::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
sprintf(buffer, "%s", ability->getMenuText());
|
||||
mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT);
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = ability->source->getThumb();
|
||||
if (quad){
|
||||
float scale = 30 / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x , y , 0,scale,scale);
|
||||
}else{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
StackAbility::StackAbility(int id,MTGAbility * _ability): Interruptible(id),ability(_ability){
|
||||
type=ACTION_ABILITY;
|
||||
}
|
||||
|
||||
|
||||
/* Spell Cast */
|
||||
|
||||
Spell::Spell(MTGCardInstance * _source): Interruptible(0), TargetsList(){
|
||||
source = _source;
|
||||
mHeight= 40;
|
||||
type = ACTION_SPELL;
|
||||
cost = NEW ManaCost();
|
||||
}
|
||||
|
||||
|
||||
Spell::Spell(int id, MTGCardInstance * _source, Targetable * _targets[], int nb_targets, ManaCost * _cost): Interruptible(id), TargetsList(_targets, nb_targets),cost(_cost){
|
||||
source = _source;
|
||||
mHeight = 40;
|
||||
type = ACTION_SPELL;
|
||||
}
|
||||
|
||||
|
||||
Spell::~Spell(){
|
||||
SAFE_DELETE(cost);
|
||||
}
|
||||
|
||||
int Spell::resolve(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
//TODO Remove target if it's not targettable anymore
|
||||
source->controller()->game->putInPlay(source);
|
||||
AbilityFactory af;
|
||||
af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Spell::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
sprintf(buffer, "%s", source->model->getName());
|
||||
mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT);
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = source->getThumb();
|
||||
if (quad){
|
||||
float scale = mHeight / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x , y , 0,scale,scale);
|
||||
}else{
|
||||
//TODO
|
||||
}
|
||||
Damageable * target = getNextDamageableTarget();
|
||||
if (target){
|
||||
quad = target->getIcon();
|
||||
if (quad){
|
||||
float scale = 30 / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Put a card in graveyard */
|
||||
|
||||
PutInGraveyard::PutInGraveyard(int id, MTGCardInstance * _card):Interruptible(id){
|
||||
card = _card;
|
||||
removeFromGame = 0;
|
||||
type = ACTION_PUTINGRAVEYARD;
|
||||
}
|
||||
|
||||
int PutInGraveyard::resolve(){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
MTGGameZone * zone = card->getCurrentZone();
|
||||
if (zone == g->players[0]->game->inPlay || zone == g->players[1]->game->inPlay){
|
||||
card->owner->game->putInZone(card,zone,card->owner->game->graveyard);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PutInGraveyard::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
if (!removeFromGame){
|
||||
mFont->DrawString("goes to graveyard", x + 20 , y, JGETEXT_LEFT);
|
||||
}else{
|
||||
mFont->DrawString("is removed from game", x + 20 , y, JGETEXT_LEFT);
|
||||
}
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = card->getThumb();
|
||||
if (quad){
|
||||
float scale = 30 / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x , y , 0,scale,scale);
|
||||
}else{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Draw a Card */
|
||||
DrawAction::DrawAction(int id, Player * _player, int _nbcards):Interruptible(id), nbcards(_nbcards), player(_player){
|
||||
}
|
||||
|
||||
int DrawAction::resolve(){
|
||||
for (int i = 0 ; i < nbcards ; i++){
|
||||
player->game->drawFromLibrary();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DrawAction::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
int playerId = 1;
|
||||
if (player == GameObserver::GetInstance()->players[1]) playerId = 2;
|
||||
sprintf(buffer, "Player %i draws %i card", playerId, nbcards);
|
||||
mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT);
|
||||
}
|
||||
|
||||
/* The Action Stack itself */
|
||||
int ActionStack::addPutInGraveyard(MTGCardInstance * card){
|
||||
PutInGraveyard * death = NEW PutInGraveyard(mCount,card);
|
||||
addAction(death);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addAbility(MTGAbility * ability){
|
||||
StackAbility * stackAbility = NEW StackAbility(mCount,ability);
|
||||
addAction(stackAbility);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addDraw(Player * player, int nb_cards){
|
||||
DrawAction * draw = NEW DrawAction(mCount,player, nb_cards);
|
||||
addAction(draw);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addDamage(MTGCardInstance * _source, Damageable * _target, int _damage){
|
||||
Damage * damage = NEW Damage(mCount, _source, _target, _damage);
|
||||
addAction(damage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::AddNextGamePhase(){
|
||||
if (getNext(NULL,NOT_RESOLVED)) return 0;
|
||||
NextGamePhase * next = NEW NextGamePhase(mCount);
|
||||
addAction(next);
|
||||
int playerId = 0;
|
||||
if (game->currentActionPlayer == game->players[1]) playerId = 1;
|
||||
interruptDecision[playerId] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::setIsInterrupting(Player * player){
|
||||
if (player == game->players[0]){
|
||||
interruptDecision[0] = -1;
|
||||
}else{
|
||||
interruptDecision[1] = -1;
|
||||
}
|
||||
game->isInterrupting = player;
|
||||
askIfWishesToInterrupt = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ActionStack::addAction(Interruptible * action){
|
||||
for (int i=0; i<2; i++){
|
||||
interruptDecision[i] = 0;
|
||||
}
|
||||
Add(action);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::addSpell(MTGCardInstance * _source, Targetable * _targets[], int _nbtargets, ManaCost * mana){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096], *p = buf;
|
||||
sprintf(buf, "Add spell\n");
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
Spell * spell = NEW Spell(mCount,_source,_targets,_nbtargets, mana);
|
||||
return addAction(spell);
|
||||
}
|
||||
|
||||
|
||||
Interruptible * ActionStack::_(int id){
|
||||
if (id < 0) id = mCount + id;
|
||||
if (id > mCount -1) return NULL;
|
||||
return (Interruptible *)mObjects[id];
|
||||
}
|
||||
|
||||
ActionStack::ActionStack(int id, GameObserver* _game):GuiLayer(id, _game){
|
||||
for (int i=0; i<2; i++){
|
||||
interruptDecision[i] = 0;
|
||||
}
|
||||
askIfWishesToInterrupt = NULL;
|
||||
timer = -1;
|
||||
currentState = -1;
|
||||
mode = ACTIONSTACK_STANDARD;
|
||||
checked = 0;
|
||||
|
||||
}
|
||||
|
||||
int ActionStack::has(Interruptible * action){
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
if (mObjects[i] == action) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ActionStack::resolve(){
|
||||
Interruptible * action = getLatest(NOT_RESOLVED);
|
||||
|
||||
if (!action)
|
||||
return 0;
|
||||
|
||||
|
||||
if (action->resolve()){
|
||||
action->state = RESOLVED_OK;
|
||||
}else{
|
||||
action->state = RESOLVED_NOK;
|
||||
}
|
||||
if (action->type == ACTION_DAMAGE) ((Damage * )action)->target->afterDamage();
|
||||
if (action->type == ACTION_DAMAGES){
|
||||
DamageStack * ds = (DamageStack *) action;
|
||||
for (int i = 0; i < ds->mCount; i++){
|
||||
Damage * damage = ((Damage *) ds->mObjects[i]);
|
||||
damage->state = ds->state;
|
||||
}
|
||||
unpackDamageStack(ds);
|
||||
ds->mCount = 0;
|
||||
}
|
||||
|
||||
if (!getNext(NULL,NOT_RESOLVED)){
|
||||
for (int i = 0; i< 2 ; i++){
|
||||
interruptDecision[i] = 0;
|
||||
}
|
||||
}else{
|
||||
for (int i = 0; i< 2 ; i++){
|
||||
if (interruptDecision[i] != 2) interruptDecision[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
Interruptible * ActionStack::getPrevious(Interruptible * next, int type, int state, int display){
|
||||
int n = getPreviousIndex( next, type, state, display);
|
||||
if (n==-1) return NULL;
|
||||
return ((Interruptible *) mObjects[n]);
|
||||
}
|
||||
|
||||
int ActionStack::getPreviousIndex(Interruptible * next, int type, int state, int display){
|
||||
int found = 0;
|
||||
if (!next) found = 1;
|
||||
for (int i = mCount -1; i >= 0 ; i--){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){
|
||||
return i;
|
||||
}
|
||||
if (current == next) found = 1;
|
||||
}
|
||||
if (!found) return getPreviousIndex(NULL,type, state, display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ActionStack::count( int type, int state, int display){
|
||||
int result = 0;
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if((type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display){
|
||||
int n = getNextIndex( previous, type, state, display);
|
||||
if (n==-1) return NULL;
|
||||
return ((Interruptible *) mObjects[n]);
|
||||
}
|
||||
|
||||
int ActionStack::getNextIndex(Interruptible * previous, int type, int state, int display){
|
||||
int found = 0;
|
||||
if (!previous) found = 1;
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (found && (type == 0 || current->type == type) && (state == 0 || current->state == state) && (display == -1 || current->display == display)){
|
||||
return i;
|
||||
}
|
||||
if (current == previous) found = 1;
|
||||
}
|
||||
if (!found) return getNextIndex(NULL,type, state, display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Interruptible * ActionStack::getLatest(int state){
|
||||
for (int i = mCount-1; i >=0; i--){
|
||||
Interruptible * action = ((Interruptible *)mObjects[i]);
|
||||
if (action->state == state) return action;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ActionStack::unpackDamageStack(DamageStack * ds){
|
||||
for (int j = 0; j < ds->mCount; j++){
|
||||
Damage * damage = ((Damage *)ds->mObjects[j]);
|
||||
Add(damage);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionStack::unpackDamageStacks(){
|
||||
for (int i = mCount-1; i >=0; i--){
|
||||
Interruptible * action = ((Interruptible *)mObjects[i]);
|
||||
if (action->type == ACTION_DAMAGES){
|
||||
DamageStack * ds = (DamageStack *) action;
|
||||
unpackDamageStack(ds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionStack::repackDamageStacks(){
|
||||
for (int i = mCount-1; i >=0; i--){
|
||||
Interruptible * action = ((Interruptible *)mObjects[i]);
|
||||
if (action->type == ACTION_DAMAGE){
|
||||
Damage * damage = (Damage *) action;
|
||||
for (int j = 0; j < mCount; j++){
|
||||
Interruptible * action2 = ((Interruptible *)mObjects[j]);
|
||||
if (action->type == ACTION_DAMAGES){
|
||||
DamageStack * ds = (DamageStack *) action2;
|
||||
for (int k = 0; k< ds->mCount; k++){
|
||||
Damage * dsdamage = ((Damage *)ds->mObjects[k]);
|
||||
if (dsdamage==damage) Remove(damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionStack::Update(float dt){
|
||||
askIfWishesToInterrupt = NULL;
|
||||
//modal = 0;
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
TargetChooser * tc = game->getCurrentTargetChooser();
|
||||
int newState = game->getCurrentGamePhase();
|
||||
currentState = newState;
|
||||
|
||||
//Select Stack's display mode
|
||||
if (mode==ACTIONSTACK_STANDARD && tc && !checked){
|
||||
checked = 1;
|
||||
unpackDamageStacks();
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (tc->canTarget(current)){
|
||||
if (mObjects[mCurr]) mObjects[mCurr]->Leaving(PSP_CTRL_UP);
|
||||
current->display = 1;
|
||||
mCurr = i;
|
||||
mObjects[mCurr]->Entering();
|
||||
mode=ACTIONSTACK_TARGET;
|
||||
modal = 1;
|
||||
}else{
|
||||
current->display = 0;
|
||||
}
|
||||
}
|
||||
if (mode != ACTIONSTACK_TARGET){
|
||||
repackDamageStacks();
|
||||
}
|
||||
}else if (mode==ACTIONSTACK_TARGET && !tc){
|
||||
mode = ACTIONSTACK_STANDARD;
|
||||
checked = 0;
|
||||
repackDamageStacks();
|
||||
}
|
||||
|
||||
if (mode == ACTIONSTACK_STANDARD){
|
||||
modal = 0;
|
||||
if (getLatest(NOT_RESOLVED)){
|
||||
int currentPlayerId = 0;
|
||||
int otherPlayerId = 1;
|
||||
if (game->currentPlayer != game->players[0]){
|
||||
currentPlayerId = 1;
|
||||
otherPlayerId = 0;
|
||||
}
|
||||
if (interruptDecision[currentPlayerId] == 0){
|
||||
askIfWishesToInterrupt = game->players[currentPlayerId];
|
||||
game->isInterrupting = game->players[currentPlayerId];
|
||||
modal = 1;
|
||||
}else if (interruptDecision[currentPlayerId] == -1){
|
||||
game->isInterrupting = game->players[currentPlayerId];
|
||||
|
||||
}else{
|
||||
if (interruptDecision[otherPlayerId] == 0){
|
||||
askIfWishesToInterrupt = game->players[otherPlayerId];
|
||||
game->isInterrupting = game->players[otherPlayerId];
|
||||
modal = 1;
|
||||
}else if (interruptDecision[otherPlayerId] == -1){
|
||||
game->isInterrupting = game->players[otherPlayerId];
|
||||
}else{
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if (mode == ACTIONSTACK_TARGET){
|
||||
GuiLayer::Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionStack::cancelInterruptOffer(int cancelMode){
|
||||
if (askIfWishesToInterrupt == game->players[0]){
|
||||
interruptDecision[0] = cancelMode;
|
||||
}else{
|
||||
interruptDecision[1] = cancelMode;
|
||||
}
|
||||
askIfWishesToInterrupt = NULL;
|
||||
game->isInterrupting = NULL;
|
||||
timer = -1;
|
||||
}
|
||||
|
||||
void ActionStack::endOfInterruption(){
|
||||
if (game->isInterrupting == game->players[0]){
|
||||
interruptDecision[0] = 0;
|
||||
}else{
|
||||
interruptDecision[1] = 0;
|
||||
}
|
||||
game->isInterrupting = NULL;
|
||||
}
|
||||
|
||||
|
||||
void ActionStack::CheckUserInput(float dt){
|
||||
if (mode == ACTIONSTACK_STANDARD){
|
||||
if (askIfWishesToInterrupt){
|
||||
if (timer < 0) timer = 300;
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CROSS)){
|
||||
setIsInterrupting(askIfWishesToInterrupt);
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE) ||mEngine->GetButtonClick(PSP_CTRL_RTRIGGER) ){
|
||||
cancelInterruptOffer();
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_SQUARE)){
|
||||
cancelInterruptOffer(2);
|
||||
}else{
|
||||
timer --;
|
||||
if (timer < 0){
|
||||
cancelInterruptOffer();
|
||||
}
|
||||
}
|
||||
}else if (game->isInterrupting){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CROSS)){
|
||||
endOfInterruption();
|
||||
}
|
||||
}
|
||||
}else if (mode == ACTIONSTACK_TARGET){
|
||||
if (modal){
|
||||
if (mEngine->GetButtonState(PSP_CTRL_UP)){
|
||||
if (KeyRepeated(PSP_CTRL_UP, dt))
|
||||
{
|
||||
if( mObjects[mCurr]){
|
||||
int n = getPreviousIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1);
|
||||
if (n != -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_UP))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Stack UP TO mCurr = %i\n", mCurr);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if (mEngine->GetButtonState(PSP_CTRL_DOWN)){
|
||||
if (KeyRepeated(PSP_CTRL_DOWN, dt))
|
||||
{
|
||||
if( mObjects[mCurr]){
|
||||
int n = getNextIndex(((Interruptible *) mObjects[mCurr]), 0, 0, 1);
|
||||
if (n!= -1 && n != mCurr && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Stack DOWN TO mCurr = %i\n", mCurr);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Stack CLIKED mCurr = %i\n", mCurr);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
game->stackObjectClicked(((Interruptible *) mObjects[mCurr]));
|
||||
}
|
||||
}
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_TRIANGLE)){
|
||||
if (modal) {modal = 0;} else {modal = 1;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ActionStack::CombatDamages(){
|
||||
CombatDamages(1);
|
||||
CombatDamages(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ActionStack::CombatDamages(int strike){
|
||||
DamageStack * damages = NEW DamageStack(mCount,game);
|
||||
int damageitems = damages->CombatDamages(strike);
|
||||
if (damageitems){
|
||||
addAction(damages);
|
||||
}else{
|
||||
delete damages;
|
||||
}
|
||||
return damageitems;
|
||||
}
|
||||
|
||||
//Cleans history of last turn
|
||||
int ActionStack::garbageCollect(){
|
||||
for (int i=mCount-1;i>=0; i--){
|
||||
Interruptible * current = ((Interruptible *)mObjects[i]);
|
||||
if (current->state != NOT_RESOLVED){
|
||||
mObjects[i] = mObjects[mCount-1];
|
||||
mCount--;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ActionStack::Fizzle(Interruptible * action){
|
||||
if (action->type == ACTION_SPELL){
|
||||
Spell * spell = (Spell *) action;
|
||||
spell->source->controller()->game->putInGraveyard(spell->source);
|
||||
}
|
||||
action->state = RESOLVED_NOK;
|
||||
}
|
||||
|
||||
void ActionStack::Render(){
|
||||
int x0 = 250;
|
||||
int y0 = 30;
|
||||
int width = 200;
|
||||
int height = 90;
|
||||
int currenty = y0 + 5 ;
|
||||
|
||||
if (mode == ACTIONSTACK_STANDARD){
|
||||
if (!askIfWishesToInterrupt || !askIfWishesToInterrupt->displayStack()) return;
|
||||
|
||||
|
||||
for (int i=0;i<mCount ;i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (current->state==NOT_RESOLVED) height += current->mHeight;
|
||||
}
|
||||
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
|
||||
//JQuad * back = GameApp::CommonRes->GetQuad("interrupt");
|
||||
//float xScale = width / back->mWidth;
|
||||
//float yScale = height / back->mHeight;
|
||||
renderer->FillRoundRect(x0 + 16 ,y0 + 16 ,width +2 ,height +2 , 10, ARGB(128,0,0,0));
|
||||
renderer->FillRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(200,0,0,0));
|
||||
//renderer->RenderQuad(back,x0,y0,0,xScale, yScale);
|
||||
renderer->DrawRoundRect(x0 - 5 ,y0 - 5 ,width + 2,height +2 , 10, ARGB(255,255,255,255));
|
||||
|
||||
|
||||
for (int i=0;i<mCount ;i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (current && current->state==NOT_RESOLVED){
|
||||
current->x = x0 + 5;
|
||||
if (i != mCount -1){
|
||||
current->y = currenty;
|
||||
currenty += current->mHeight;
|
||||
}else{
|
||||
current->y = currenty + 40 ;
|
||||
currenty += current->mHeight + 40;
|
||||
}
|
||||
current->Render();
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[200];
|
||||
sprintf(buffer, "interrupt ? %i", timer/100);
|
||||
mFont->DrawString(buffer, x0 + 5 , currenty - 40 - ((Interruptible *)mObjects[mCount-1])->mHeight);
|
||||
|
||||
if (mCount > 1){
|
||||
sprintf(buffer, "X Interrupt - 0 No - [] No to All");
|
||||
}else{
|
||||
sprintf(buffer, "X Interrupt - 0 No");
|
||||
}
|
||||
mFont->DrawString(buffer, x0 + 5 , currenty);
|
||||
}else if (mode == ACTIONSTACK_TARGET && modal){
|
||||
for (int i=0;i<mCount ;i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (current->display) height += current->mHeight;
|
||||
}
|
||||
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(x0 ,y0 , width ,height , ARGB(200,0,0,0));
|
||||
renderer->DrawRect(x0 - 1 ,y0 - 1 ,width + 2 ,height +2 , ARGB(255,255,255,255));
|
||||
|
||||
|
||||
for (int i=0;i<mCount ;i++){
|
||||
Interruptible * current = (Interruptible *)mObjects[i];
|
||||
if (mObjects[i]!=NULL && current->display){
|
||||
((Interruptible *)mObjects[i])->x = x0 + 5;
|
||||
if (i != mCount -1){
|
||||
((Interruptible *)mObjects[i])->y = currenty;
|
||||
currenty += ((Interruptible *)mObjects[i])->mHeight;
|
||||
}else{
|
||||
((Interruptible *)mObjects[i])->y = currenty + 40 ;
|
||||
currenty += ((Interruptible *)mObjects[i])->mHeight + 40;
|
||||
}
|
||||
mObjects[i]->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Blocker.h"
|
||||
|
||||
Blocker::Blocker(int id, MTGCardInstance * card):MTGAbility(id, card){
|
||||
init ( NEW ManaCost());
|
||||
}
|
||||
|
||||
Blocker::Blocker(int id, MTGCardInstance * card, ManaCost * _cost):MTGAbility(id, card){
|
||||
init(_cost);
|
||||
}
|
||||
|
||||
Blocker::Blocker(int id, MTGCardInstance * card, MTGCardInstance *_target, ManaCost * _cost):MTGAbility(id, card,_target){
|
||||
init(_cost);
|
||||
}
|
||||
|
||||
Blocker::~Blocker(){
|
||||
delete manaCost;
|
||||
}
|
||||
|
||||
void Blocker::init(ManaCost * _cost){
|
||||
currentPhase = -1;
|
||||
manaCost = _cost;
|
||||
}
|
||||
|
||||
|
||||
//Default behaviour for blockers : they block the card they're attached to
|
||||
void Blocker::Update(float dt){
|
||||
game = GameObserver::GetInstance();
|
||||
int newPhase = game->getCurrentGamePhase();
|
||||
if (newPhase != currentPhase){
|
||||
MTGCardInstance * _target;
|
||||
if (target){
|
||||
_target = (MTGCardInstance *) target;
|
||||
}else{
|
||||
_target = source;
|
||||
}
|
||||
_target->getBlockers()->Add(this);
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Adding Blocker to %s \n", _target->model->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
}
|
||||
currentPhase = newPhase;
|
||||
}
|
||||
|
||||
int Blocker::destroy(){
|
||||
MTGCardInstance * _target;
|
||||
if (target){
|
||||
_target = (MTGCardInstance *) target;
|
||||
}else{
|
||||
_target = source;
|
||||
}
|
||||
_target->getBlockers()->Remove(this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Blockers::Blockers(){
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Blockers::init(){
|
||||
cursor = -1;
|
||||
|
||||
for (int i=0; i< MAX_BLOCKERS ; i++){
|
||||
blockers[i] = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Blockers::Add (Blocker * ability){
|
||||
game = GameObserver::GetInstance();
|
||||
int index = game->mLayers->actionLayer()->getIndexOf(ability);
|
||||
blockers[index] = 1;
|
||||
return index;
|
||||
}
|
||||
int Blockers::Remove (Blocker * ability){
|
||||
game = GameObserver::GetInstance();
|
||||
int index = game->mLayers->actionLayer()->getIndexOf(ability);
|
||||
blockers[index] = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
int Blockers::rewind(){
|
||||
cursor = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Blocker * Blockers::next(){
|
||||
cursor++;
|
||||
game = GameObserver::GetInstance();
|
||||
while (blockers[cursor] == 0){
|
||||
cursor ++;
|
||||
if (cursor == MAX_BLOCKERS){
|
||||
cursor = -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (Blocker *) (game->mLayers->actionLayer()->getByIndex(cursor));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Blockers::isEmpty(){
|
||||
for (int i=0; i< MAX_BLOCKERS ; i++){
|
||||
if (blockers[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Blockers::~Blockers(){
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/CardDescriptor.h"
|
||||
|
||||
CardDescriptor::CardDescriptor(): MTGCardInstance(){
|
||||
init();
|
||||
}
|
||||
|
||||
int CardDescriptor::init(){
|
||||
return MTGCardInstance::init();
|
||||
}
|
||||
|
||||
MTGCardInstance * CardDescriptor::match(MTGCardInstance * card){
|
||||
|
||||
MTGCardInstance * match = card;
|
||||
for (int i = 0; i< nb_types; i++){
|
||||
|
||||
if (!card->hasSubtype(types[i])){
|
||||
|
||||
match = NULL;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i< MTG_NB_COLORS; i++){
|
||||
if ((colors[i] == 1 && !card->hasColor(i))||(colors[i] == -1 && card->hasColor(i))){
|
||||
match = NULL;
|
||||
}
|
||||
}
|
||||
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())){
|
||||
match = NULL;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
MTGCardInstance * CardDescriptor::match(MTGGameZone * zone){
|
||||
return (nextmatch(zone, NULL));
|
||||
}
|
||||
|
||||
MTGCardInstance * CardDescriptor::nextmatch(MTGGameZone * zone, MTGCardInstance * previous){
|
||||
int found = 0;
|
||||
if (NULL == previous) found = 1;
|
||||
for(int i=0; i < zone->nb_cards; i++){
|
||||
if(found && match(zone->cards[i])){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf,"Card Descriptor MATCH!: %s \n" ,(zone->cards[i])->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
return zone->cards[i];
|
||||
}
|
||||
if (zone->cards[i] == previous){
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/CardDisplay.h"
|
||||
#include "../include/CardGui.h"
|
||||
#include "../include/TargetChooser.h"
|
||||
#include "../include/MTGGameZones.h"
|
||||
|
||||
CardDisplay::CardDisplay():PlayGuiObjectController(0, GameObserver::GetInstance()){
|
||||
tc= NULL;
|
||||
listener = NULL;
|
||||
nb_displayed_items = 7;
|
||||
start_item = 0;
|
||||
x= 0;
|
||||
y= 0;
|
||||
}
|
||||
|
||||
CardDisplay::CardDisplay(int id, GameObserver* _game, int _x, int _y, JGuiListener * _listener, TargetChooser * _tc, int _nb_displayed_items ):PlayGuiObjectController(id, _game), x(_x), y(_y){
|
||||
tc= _tc;
|
||||
listener = _listener;
|
||||
nb_displayed_items = _nb_displayed_items;
|
||||
start_item = 0;
|
||||
}
|
||||
|
||||
|
||||
void CardDisplay::AddCard(MTGCardInstance * _card){
|
||||
CardGui * card = NEW CardGui(mCount, _card, 40, x + 5 + (mCount - start_item) * 30, y + 5, (mCount == 0));
|
||||
Add(card);
|
||||
}
|
||||
|
||||
|
||||
void CardDisplay::init(MTGGameZone * zone){
|
||||
resetObjects();
|
||||
start_item = 0;
|
||||
for (int i= 0; i< zone->nb_cards; i++){
|
||||
AddCard(zone->cards[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CardDisplay::rotateLeft(){
|
||||
if (start_item==0) return;
|
||||
for (int i= 0; i<mCount; i++){
|
||||
CardGui * cardg = (CardGui *)mObjects[i];
|
||||
cardg->x+=30;
|
||||
}
|
||||
start_item --;
|
||||
}
|
||||
|
||||
void CardDisplay::rotateRight(){
|
||||
if (start_item==mCount-1) return;
|
||||
for (int i= 0; i<mCount; i++){
|
||||
CardGui * cardg = (CardGui *)mObjects[i];
|
||||
cardg->x-=30;
|
||||
}
|
||||
start_item ++;
|
||||
}
|
||||
|
||||
|
||||
void CardDisplay::CheckUserInput(float dt){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CROSS))
|
||||
{
|
||||
if (listener != NULL)
|
||||
{
|
||||
listener->ButtonPressed(mId, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!mCount)
|
||||
return;
|
||||
|
||||
if (mEngine->GetButtonClick(mActionButton))
|
||||
{
|
||||
if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){
|
||||
CardGui * cardg = (CardGui *)mObjects[mCurr];
|
||||
if (tc)
|
||||
{
|
||||
tc->toggleTarget(cardg->card);
|
||||
return;
|
||||
}else{
|
||||
if (game) game->ButtonPressed(mId, cardg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mEngine->GetButtonState(PSP_CTRL_LEFT))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_LEFT, dt))
|
||||
{
|
||||
int n = mCurr;
|
||||
n--;
|
||||
if (n<start_item){
|
||||
if (n< 0){n = 0;}
|
||||
else{ rotateLeft();}
|
||||
}
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_LEFT)){
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonState(PSP_CTRL_RIGHT))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_RIGHT, dt))
|
||||
{
|
||||
int n = mCurr;
|
||||
n++;
|
||||
if (n>= start_item + nb_displayed_items){
|
||||
if (n>= mCount){n = mCount-1;}
|
||||
else{ rotateRight();}
|
||||
}
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_RIGHT)){
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else{
|
||||
mLastKey = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CardDisplay::Render(){
|
||||
|
||||
JRenderer * r = JRenderer::GetInstance();
|
||||
r->DrawRect(x,y,nb_displayed_items * 30 + 20, 50, ARGB(255,255,255,255));
|
||||
if (!mCount) return;
|
||||
for (int i = start_item; i< start_item + nb_displayed_items && i < mCount; i++){
|
||||
if (mObjects[i]){
|
||||
mObjects[i]->Render();
|
||||
if (tc){
|
||||
CardGui * cardg = (CardGui *)mObjects[i];
|
||||
if( tc->alreadyHasTarget(cardg->card)){
|
||||
r->DrawCircle(cardg->x + 5, cardg->y+5,5, ARGB(255,255,0,0));
|
||||
}else if (!tc->canTarget(cardg->card)){
|
||||
r->FillRect(cardg->x,cardg->y,30,40,ARGB(200,0,0,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mObjects[mCurr]){
|
||||
mObjects[mCurr]->Render();
|
||||
}
|
||||
}
|
||||
|
||||
DefaultTargetDisplay::DefaultTargetDisplay(int id, GameObserver* _game, int _x, int _y,JGuiListener * _listener, int _nb_displayed_items ):CardDisplay(id, _game, _x, _y, _listener, NULL, _nb_displayed_items ){
|
||||
tc = NEW TargetChooser();
|
||||
}
|
||||
|
||||
DefaultTargetDisplay::~DefaultTargetDisplay(){
|
||||
SAFE_DELETE(tc);
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/CardGui.h"
|
||||
#include <Vector2D.h>
|
||||
|
||||
void CardGui::alternateRender(MTGCard * card, JLBFont * mFont, JQuad ** manaIcons, float x, float y, float rotation, float scale){
|
||||
JQuad * mIcons[7];
|
||||
if (!manaIcons){
|
||||
mIcons[MTG_COLOR_ARTIFACT] = GameApp::CommonRes->GetQuad("c_artifact");
|
||||
mIcons[MTG_COLOR_LAND] = GameApp::CommonRes->GetQuad("c_land");
|
||||
mIcons[MTG_COLOR_WHITE] = GameApp::CommonRes->GetQuad("c_white");
|
||||
mIcons[MTG_COLOR_RED] = GameApp::CommonRes->GetQuad("c_red");
|
||||
mIcons[MTG_COLOR_BLACK] = GameApp::CommonRes->GetQuad("c_black");
|
||||
mIcons[MTG_COLOR_BLUE] = GameApp::CommonRes->GetQuad("c_blue");
|
||||
mIcons[MTG_COLOR_GREEN] = GameApp::CommonRes->GetQuad("c_green");
|
||||
for (int i=0; i < 7; i++){
|
||||
mIcons[i]->SetHotSpot(16,16);
|
||||
}
|
||||
manaIcons = mIcons;
|
||||
}
|
||||
Vector2D v;
|
||||
Vector2D points[4];
|
||||
PIXEL_TYPE bgcolor = ARGB(255,128,128,128);
|
||||
PIXEL_TYPE bgcolor2 = ARGB(255,80,80,80);
|
||||
char buf[25];
|
||||
int width = 200;
|
||||
int height = 285;
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
mFont->SetRotation(rotation);
|
||||
mFont->SetScale(scale);
|
||||
|
||||
int color = card->getColor();
|
||||
|
||||
points[0].x = -width/2;
|
||||
points[0].y = -height/2 ;
|
||||
points[1].x = width/2;
|
||||
points[1].y = -height/2;
|
||||
points[2].x = width/2;
|
||||
points[2].y = height/2;
|
||||
points[3].x = -width/2;
|
||||
points[3].y = height/2;
|
||||
|
||||
for (int i=0; i < 4; i++){
|
||||
points[i].x *= scale;
|
||||
points[i].y *= scale;
|
||||
points[i].Rotate(rotation);
|
||||
}
|
||||
|
||||
if (rotation == 0){
|
||||
renderer->FillRoundRect(x+points[0].x + 2 ,y+points[0].y +2 ,width*scale-8,height*scale-8,2,ARGB(255,_r[color],_g[color],_b[color]));
|
||||
renderer->FillRect(x+points[0].x + 6 ,y+points[0].y + 6 ,width*scale-12,height*scale-12,bgcolor2);
|
||||
}else{
|
||||
for (int i=0; i < 4; i++){
|
||||
renderer->DrawLine(x + points[i].x,y + points[i].y,x + points[(i+1)%4].x,y + points[(i+1)%4].y,bgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ManaCost * manacost = card->getManaCost();
|
||||
int nbicons = 0;
|
||||
for (int i = 1; i < MTG_NB_COLORS - 1; i++){
|
||||
int cost = manacost->getCost(i);
|
||||
for (int j=0; j < cost; j++){
|
||||
v.x = (width/2 - 20 - 16*nbicons)*scale;
|
||||
v.y = ((-height/2) + 20) * scale;
|
||||
v.Rotate(rotation);
|
||||
renderer->RenderQuad(manaIcons[i],x+v.x,y+v.y,rotation,0.5*scale, 0.5*scale);
|
||||
nbicons++;
|
||||
}
|
||||
}
|
||||
int cost = manacost->getCost(0);
|
||||
if (cost !=0){
|
||||
v.x = (width/2 - 20 - 16*nbicons)*scale;
|
||||
v.y = ((-height/2) + 14) * scale;
|
||||
v.Rotate(rotation);
|
||||
sprintf(buf,"%i",cost);
|
||||
mFont->DrawString(buf,x+v.x,y+v.y);
|
||||
}
|
||||
|
||||
|
||||
if (!card->formattedTextInit){
|
||||
std::string s(card->getText());
|
||||
unsigned int found=s.find_first_of("{}");
|
||||
while (found!=string::npos)
|
||||
{
|
||||
s[found]='/';
|
||||
found=s.find_first_of("{}",found+1);
|
||||
}
|
||||
int len = 24;
|
||||
while (s.length() > 0){
|
||||
int cut = s.find_first_of("., \t)", 0);
|
||||
if (cut >= len || cut == -1){
|
||||
card->formattedText.push_back(s.substr(0,len));
|
||||
if ((signed int)s.length() > len){
|
||||
s = s.substr(len,s.length()-len);
|
||||
}else{
|
||||
s = "";
|
||||
}
|
||||
}else{
|
||||
int newcut = cut;
|
||||
while (newcut < len && newcut != -1){
|
||||
cut = newcut;
|
||||
newcut = s.find_first_of("., \t)", newcut + 1);
|
||||
}
|
||||
card->formattedText.push_back(s.substr(0,cut+1));
|
||||
if ((signed int)s.length() > cut+1){
|
||||
s = s.substr(cut+1,s.length()- cut - 1);
|
||||
}else{
|
||||
s = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
card->formattedTextInit = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (unsigned int i=0; i < card->formattedText.size(); i++){
|
||||
sprintf(buf, "%s", card->formattedText[i].c_str());
|
||||
v.x = (-width/2 + 12 )*scale;
|
||||
v.y = ((-height/2) + 50 + 16*i) * scale;
|
||||
v.Rotate(rotation);
|
||||
mFont->DrawString(buf,x+v.x,y+v.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
v.x = ((-width/2)+10) * scale;
|
||||
v.y = ((-height/2) + 25) * scale;
|
||||
v.Rotate(rotation);
|
||||
int over = strlen(card->getName()) - 23;
|
||||
float multiply = 1.4;
|
||||
if (over > 0){
|
||||
multiply = 1.1;
|
||||
}
|
||||
mFont->SetScale(scale * multiply);
|
||||
mFont->SetColor(ARGB(255,_r[color],_g[color],_b[color]));
|
||||
mFont->DrawString(card->getName(),x+v.x,y+v.y);
|
||||
mFont->SetScale(scale);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
|
||||
|
||||
if (card->isACreature()){
|
||||
v.x = (width/2-40) * scale;
|
||||
v.y = (height/2-30) * scale;
|
||||
v.Rotate(rotation);
|
||||
sprintf(buf,"%i/%i",card->power,card->toughness);
|
||||
mFont->DrawString(buf,x+v.x,y+v.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
CardGui::CardGui(int id, MTGCardInstance * _card, float desiredHeight,float _x, float _y, bool hasFocus): PlayGuiObject(id, desiredHeight, _x, _y, hasFocus){
|
||||
LOG("==Creating NEW CardGui Object. CardName:");
|
||||
LOG(_card->getName());
|
||||
|
||||
card = _card;
|
||||
type = GUI_CARD;
|
||||
|
||||
alpha = 255;
|
||||
mParticleSys = NULL;
|
||||
|
||||
if (card->hasColor(MTG_COLOR_RED)){
|
||||
mParticleSys = GameApp::Particles[3];
|
||||
}else if (card->hasColor(MTG_COLOR_BLUE)){
|
||||
mParticleSys = GameApp::Particles[1];
|
||||
}else if (card->hasColor(MTG_COLOR_GREEN)){
|
||||
mParticleSys = GameApp::Particles[2];
|
||||
}else if (card->hasColor(MTG_COLOR_BLACK)){
|
||||
mParticleSys = GameApp::Particles[4];
|
||||
}else if (card->hasColor(MTG_COLOR_WHITE)){
|
||||
mParticleSys = GameApp::Particles[0];
|
||||
}else{
|
||||
mParticleSys = GameApp::Particles[5];
|
||||
}
|
||||
|
||||
LOG("==CardGui Object Creation Succesfull");
|
||||
}
|
||||
|
||||
|
||||
void CardGui::Update(float dt){
|
||||
alpha = 255;
|
||||
|
||||
if (card->changedZoneRecently > 0) alpha = 255.f - 255.f * card->changedZoneRecently;
|
||||
if (mParticleSys && card->changedZoneRecently == 1.f){
|
||||
mParticleSys->MoveTo(x+15, y+2*mHeight/3);
|
||||
mParticleSys->Fire();
|
||||
}
|
||||
if (card->changedZoneRecently){
|
||||
if (mParticleSys) mParticleSys->Update(dt);
|
||||
card->changedZoneRecently-= (5 *dt);
|
||||
if (card->changedZoneRecently < 0){
|
||||
if (mParticleSys) mParticleSys->Stop();
|
||||
}
|
||||
if (card->changedZoneRecently < -3){
|
||||
card->changedZoneRecently = 0;
|
||||
mParticleSys = NULL;
|
||||
}
|
||||
}
|
||||
PlayGuiObject::Update(dt);
|
||||
}
|
||||
|
||||
void CardGui::RenderBig(float xpos, float ypos){
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = card->getQuad();
|
||||
if (xpos == -1){
|
||||
xpos = 300;
|
||||
if (x > SCREEN_WIDTH / 2)
|
||||
xpos = 10;
|
||||
}
|
||||
if(ypos == -1)
|
||||
ypos = 20;
|
||||
if (quad){
|
||||
quad->SetColor(ARGB(220,255,255,255));
|
||||
renderer->RenderQuad(quad, xpos , ypos , 0.0f,0.9f,0.9f);
|
||||
}else{
|
||||
MTGCard * mtgcard = card->model;
|
||||
JLBFont * font = GameApp::CommonRes->GetJLBFont("graphics/magic");
|
||||
CardGui::alternateRender(mtgcard, font, NULL, xpos + 90 , ypos + 130, 0.0f,0.9f);
|
||||
}
|
||||
}
|
||||
|
||||
void CardGui::Render(){
|
||||
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = card->getThumb();
|
||||
if (!quad || quad->mHeight * 2 < mHeight){
|
||||
JQuad * quad2 = card->getQuad();
|
||||
if (quad2)
|
||||
quad = quad2;
|
||||
}
|
||||
|
||||
float tap = (float)(card->isTapped());
|
||||
float rotation = M_PI_2 * tap;
|
||||
if (quad){
|
||||
float mScale = mHeight / quad->mHeight;
|
||||
float myX = x + (quad->mHeight/2 * tap * mScale);
|
||||
float myY = y+(quad->mWidth/2 * tap * mScale);
|
||||
if (mHeight-defaultHeight){
|
||||
if (card->isTapped()){
|
||||
renderer->FillRect(myX + 1*(mHeight-defaultHeight) - quad->mHeight * mScale , myY + 1*(mHeight-defaultHeight) , quad->mHeight * mScale, quad->mWidth * mScale, ARGB(128,0,0,0));
|
||||
}else{
|
||||
renderer->FillRect(myX + 1*(mHeight-defaultHeight) , myY + 1*(mHeight-defaultHeight) , quad->mWidth * mScale, quad->mHeight * mScale, ARGB(128,0,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
quad->SetColor(ARGB( alpha,255,255,255));
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
TargetChooser * tc = NULL;
|
||||
if (game) tc = game->getCurrentTargetChooser();
|
||||
if (tc){
|
||||
if (!tc->canTarget(card)){
|
||||
quad->SetColor(ARGB( alpha,50,50,50));
|
||||
}
|
||||
}
|
||||
renderer->RenderQuad(quad, myX , myY , rotation,mScale,mScale);
|
||||
if (tc && tc->alreadyHasTarget(card)){
|
||||
if (card->isTapped()){
|
||||
renderer->FillRect(myX- quad->mHeight * mScale , myY , quad->mHeight * mScale, quad->mWidth * mScale, ARGB(128,255,0,0));
|
||||
}else{
|
||||
renderer->FillRect(myX , myY , quad->mWidth * mScale, quad->mHeight * mScale, ARGB(128,255,0,0));
|
||||
}
|
||||
}
|
||||
quad->SetColor(ARGB( alpha,255,255,255));
|
||||
}else{
|
||||
int color = card->getColor();
|
||||
float mScale = mHeight / 64;
|
||||
float myX = x + (32 * tap * mScale);
|
||||
float myY = y+(20 * tap * mScale);
|
||||
|
||||
char buffer[200];
|
||||
sprintf(buffer, "%s",card->getName());
|
||||
mFont->SetColor(ARGB(255,_r[color],_g[color],_b[color]));
|
||||
if (card->isTapped()){
|
||||
renderer->FillRect(myX - 64 * mScale , myY , 64 * mScale, 40 * mScale, ARGB(255,0,0,0));
|
||||
renderer->DrawRect(myX - 64 * mScale , myY , 64 * mScale, 40 * mScale, ARGB(255,_r[color],_g[color],_b[color]));
|
||||
mFont->SetScale(0.20);
|
||||
mFont->DrawString(buffer,myX - (64 * mScale)+4,myY + 1);
|
||||
}else{
|
||||
renderer->FillRect(myX , myY , 40 * mScale, 64 * mScale, ARGB(255,0,0,0));
|
||||
renderer->DrawRect(myX , myY , 40 * mScale, 64 * mScale, ARGB(255,_r[color],_g[color],_b[color]));
|
||||
mFont->SetScale(0.40);
|
||||
mFont->DrawString(buffer,myX+4,myY + 1);
|
||||
}
|
||||
|
||||
|
||||
mFont->SetScale(1.0);
|
||||
}
|
||||
if (card->isACreature()){
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
sprintf(buffer, "%i/%i",card->power,card->life);
|
||||
renderer->FillRect(x+2,y + mHeight - 12, 25 , 12 ,ARGB(128,0,0,0));
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
mFont->DrawString(buffer,x+4,y + mHeight - 10);
|
||||
}
|
||||
|
||||
if (mParticleSys && card->changedZoneRecently > 0){
|
||||
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);
|
||||
mParticleSys->Render();
|
||||
// set normal blending
|
||||
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CardGui::~CardGui(){
|
||||
LOG("==Destroying CardGui object");
|
||||
LOG(this->card->getName());
|
||||
LOG("==CardGui object destruction Successful");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/ConstraintResolver.h"
|
||||
|
||||
|
||||
int ConstraintResolver::untap(GameObserver * game, MTGCardInstance * card){
|
||||
if (!card->isUntapping()){
|
||||
return 0;
|
||||
}
|
||||
int ok = 1;
|
||||
ManaCost * untapManaCost = NEW ManaCost();
|
||||
Blockers * blockers = card->getBlockers();
|
||||
Blocker * blocker;
|
||||
blockers->rewind();
|
||||
Player * player = game->currentPlayer;
|
||||
while ((blocker = blockers->next())){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "next\n");
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
untapManaCost->add(blocker->untapManaCost());
|
||||
}
|
||||
if (player->getManaPool()->canAfford(untapManaCost)){
|
||||
blockers->rewind();
|
||||
while ((blocker = blockers->next())){
|
||||
if (!blocker->unblock()){
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
player->getManaPool()->pay(untapManaCost);
|
||||
card->untap();
|
||||
}
|
||||
delete untapManaCost;
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "../include/Counters.h"
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
|
||||
Counter::Counter(MTGCardInstance * _target, int _power, int _toughness){
|
||||
init(_target,"",_power, _toughness);
|
||||
}
|
||||
Counter::Counter(MTGCardInstance * _target, const char * _name,int _power, int _toughness ){
|
||||
init(_target,_name,_power, _toughness);
|
||||
}
|
||||
|
||||
int Counter::init(MTGCardInstance * _target,const char * _name, int _power, int _toughness){
|
||||
target = _target;
|
||||
name = _name;
|
||||
power = _power;
|
||||
toughness = _toughness;
|
||||
nb = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Counter::sameAs(const char * _name, int _power, int _toughness){
|
||||
if (power == 0 && toughness == 0) return (name.compare(_name) == 0);
|
||||
return (power == _power && toughness == _toughness);
|
||||
}
|
||||
|
||||
bool Counter::cancels(int _power, int _toughness){
|
||||
if (power == 0 && toughness == 0) return false;
|
||||
return (power == -_power && toughness == -_toughness);
|
||||
}
|
||||
|
||||
int Counter::added(){
|
||||
if (power != 0 || toughness != 0){
|
||||
target->power+= power;
|
||||
target->addToToughness(toughness);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Counter::removed(){
|
||||
if (power != 0 || toughness != 0){
|
||||
target->power-= power;
|
||||
target->addToToughness(-toughness);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Counters::Counters(MTGCardInstance * _target):target(_target){
|
||||
mCount = 0;
|
||||
}
|
||||
Counters::~Counters(){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
delete counters[i];
|
||||
}
|
||||
}
|
||||
|
||||
int Counters::addCounter(const char * _name,int _power, int _toughness){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
if (counters[i]->cancels( _power,_toughness) && counters[i]->nb > 0){
|
||||
counters[i]->removed();
|
||||
counters[i]->nb--;
|
||||
return mCount;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mCount; i++){
|
||||
if (counters[i]->sameAs(_name, _power,_toughness)){
|
||||
counters[i]->added();
|
||||
counters[i]->nb++;
|
||||
return mCount;
|
||||
}
|
||||
}
|
||||
Counter * counter = NEW Counter(target,_name, _power, _toughness);
|
||||
counters[mCount] = counter;
|
||||
counter->added();
|
||||
mCount++;
|
||||
return mCount;
|
||||
}
|
||||
|
||||
int Counters::addCounter(int _power, int _toughness){
|
||||
return addCounter("",_power, _toughness);
|
||||
}
|
||||
|
||||
int Counters::removeCounter(const char * _name,int _power, int _toughness){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
if (counters[i]->sameAs(_name, _power,_toughness)){
|
||||
if (counters[i]->nb < 1) return 0;
|
||||
counters[i]->removed();
|
||||
counters[i]->nb--;
|
||||
return mCount;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Counters::removeCounter(int _power, int _toughness){
|
||||
return removeCounter("",_power, _toughness);
|
||||
}
|
||||
|
||||
Counter * Counters::hasCounter(const char * _name,int _power, int _toughness){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
if (counters[i]->sameAs(_name, _power,_toughness)){
|
||||
if (counters[i]->nb > 0) return counters[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Counter * Counters::hasCounter(int _power , int _toughness ){
|
||||
return hasCounter("",_power, _toughness);
|
||||
}
|
||||
|
||||
Counter * Counters::getNext(Counter * previous){
|
||||
int found = 0;
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
if (found && counters[i]->nb > 0) return counters[i];
|
||||
if (counters[i] == previous) found = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Damage.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/Counters.h"
|
||||
|
||||
Damage::Damage(int id, MTGCardInstance * _source, Damageable * _target): Interruptible(id){
|
||||
init(_source, _target, _source->getPower());
|
||||
}
|
||||
|
||||
Damage::Damage(int id, MTGCardInstance * _source, Damageable * _target, int _damage): Interruptible(id){
|
||||
init(_source, _target, _damage);
|
||||
}
|
||||
|
||||
void Damage::init(MTGCardInstance * _source, Damageable * _target, int _damage){
|
||||
target = _target;
|
||||
source = _source;
|
||||
|
||||
|
||||
if (_damage < 0) _damage = 0; //Negative damages cannot happen
|
||||
damage = _damage;
|
||||
mHeight = 40;
|
||||
type = ACTION_DAMAGE;
|
||||
}
|
||||
|
||||
int Damage::resolve(){
|
||||
if (damage <0) damage = 0; //Negative damages cannot happen
|
||||
if (target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
|
||||
MTGCardInstance * _target = (MTGCardInstance *)target;
|
||||
if ((_target)->protectedAgainst(source)) return 0;
|
||||
// Damage for WITHER on creatures
|
||||
if (source->has(WITHER)){
|
||||
for (int i = 0; i < damage; i++){
|
||||
_target->counters->addCounter(-1, -1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
_target->doDamageTest = 1;
|
||||
}
|
||||
|
||||
int a = target->dealDamage(damage);
|
||||
return a;
|
||||
}
|
||||
|
||||
void Damage::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
char buffer[200];
|
||||
sprintf(buffer, "Does %i damage to", damage);
|
||||
mFont->DrawString(buffer, x + 20 , y, JGETEXT_LEFT);
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
JQuad * quad = source->getThumb();
|
||||
if (quad){
|
||||
float scale = 30 / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x , y , 0,scale,scale);
|
||||
}else{
|
||||
//TODO
|
||||
}
|
||||
quad = target->getIcon();
|
||||
if (quad){
|
||||
float scale = 30 / quad->mHeight;
|
||||
renderer->RenderQuad(quad, x + 150 , y , 0,scale,scale);
|
||||
}else{
|
||||
//TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DamageStack::DamageStack(int id, GameObserver * _game):GuiLayer(id, _game), Interruptible(id){
|
||||
currentState = -1;
|
||||
type = ACTION_DAMAGES;
|
||||
}
|
||||
|
||||
int DamageStack::CombatDamages(){
|
||||
CombatDamages(1);
|
||||
CombatDamages(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DamageStack::CombatDamages(int strike){
|
||||
mHeight = 0;
|
||||
MTGInPlay * attackers = game->currentPlayer->game->inPlay;
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
|
||||
MTGCardInstance * attacker = attackers->getNextAttacker(NULL);
|
||||
while (attacker != NULL){
|
||||
int nbdefensers = defensers->nbDefensers(attacker);
|
||||
if ((!strike && !attacker->has(FIRSTSTRIKE)) || (strike && attacker->has(FIRSTSTRIKE)) || attacker->has(DOUBLESTRIKE)){
|
||||
if (nbdefensers == 0){
|
||||
Damage * damage = NEW Damage (mCount, attacker, game->opponent());
|
||||
Add(damage);
|
||||
}else if (nbdefensers == 1){
|
||||
Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker));
|
||||
Add(damage);
|
||||
}else{
|
||||
//TODO Fetch list of defensers and allow user to choose targets
|
||||
Damage * damage = NEW Damage (mCount, attacker, defensers->getNextDefenser(NULL, attacker));
|
||||
Add(damage);
|
||||
}
|
||||
}
|
||||
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker);
|
||||
while (defenser != NULL){
|
||||
if ((!strike && !defenser->has(FIRSTSTRIKE)) || (strike && defenser->has(FIRSTSTRIKE)) || defenser->has(DOUBLESTRIKE)){
|
||||
Damage * damage = NEW Damage (mCount,defenser, attacker);
|
||||
Add(damage);
|
||||
}
|
||||
defenser = defensers->getNextDefenser(defenser, attacker);
|
||||
}
|
||||
attacker = attackers->getNextAttacker(attacker);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mCount; i++){
|
||||
Damage * damage = (Damage*)mObjects[i];
|
||||
mHeight += damage->mHeight;
|
||||
}
|
||||
|
||||
return mCount;
|
||||
}
|
||||
|
||||
int DamageStack::resolve(){
|
||||
for (int i = mCount-1; i>= 0; i--){
|
||||
Damage * damage = (Damage*)mObjects[i];
|
||||
damage->resolve();
|
||||
}
|
||||
for (int i = mCount-1; i>= 0; i--){
|
||||
Damage * damage = (Damage*)mObjects[i];
|
||||
damage->target->afterDamage();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DamageStack::Render(){
|
||||
int currenty = y;
|
||||
for (int i= 0; i < mCount; i++){
|
||||
Damage * damage = (Damage*)mObjects[i];
|
||||
damage->x = x;
|
||||
damage->y = currenty;
|
||||
currenty += damage->mHeight;
|
||||
damage->Render();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/DamageResolverLayer.h"
|
||||
#include "../include/GameObserver.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/DamagerDamaged.h"
|
||||
#include "../include/Damage.h"
|
||||
|
||||
DamageResolverLayer::DamageResolverLayer(int id, GameObserver * _game):PlayGuiObjectController(id, _game){
|
||||
currentPhase = -1;
|
||||
remainingDamageSteps = 0;
|
||||
damageStack = NULL;
|
||||
currentSource = NULL;
|
||||
buttonOk = 0;
|
||||
currentChoosingPlayer = NULL;
|
||||
}
|
||||
void DamageResolverLayer::Update(float dt){
|
||||
int newPhase = game->getCurrentGamePhase();
|
||||
if (newPhase == MTG_PHASE_COMBATDAMAGE){
|
||||
if (!game->mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)){
|
||||
|
||||
if (newPhase != currentPhase){
|
||||
init();
|
||||
}
|
||||
if (remainingDamageSteps && empty()){
|
||||
initResolve();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
remainingDamageSteps = 0;
|
||||
}
|
||||
currentPhase = newPhase;
|
||||
PlayGuiObjectController::Update(dt);
|
||||
}
|
||||
|
||||
|
||||
Player * DamageResolverLayer::whoSelectsDamagesDealtBy(MTGCardInstance * card){
|
||||
if (card->controller() == game->currentPlayer){ //Attacker
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
int nbdefensers = defensers->nbDefensers(card);
|
||||
if (nbdefensers == 0) return NULL;
|
||||
if(nbdefensers == 1 && !card->has(TRAMPLE)) return NULL;
|
||||
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card);
|
||||
while (defenser != NULL){
|
||||
if (defenser->has(BANDING)) return game->opponent();
|
||||
defenser = defensers->getNextDefenser(defenser, card);
|
||||
}
|
||||
return game->currentPlayer;
|
||||
}else{ //Defenser
|
||||
MTGInPlay * attackers = game->currentPlayer->game->inPlay;
|
||||
int nbattackers = attackers->nbPartners(card->isDefenser());
|
||||
if(nbattackers <= 1) return NULL;
|
||||
if (card->isDefenser()->banding) return game->currentPlayer;
|
||||
return game->opponent();
|
||||
}
|
||||
}
|
||||
|
||||
int DamageResolverLayer::addAutoDamageToOpponents(MTGCardInstance * card){
|
||||
if (card->controller() == game->currentPlayer){ //Attacker
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
int nbdefensers = defensers->nbDefensers(card);
|
||||
if (nbdefensers == 0){
|
||||
Damage * damage = NEW Damage (0, card, game->opponent());
|
||||
damageStack->Add(damage);
|
||||
}else if (nbdefensers == 1){
|
||||
Damage * damage = NEW Damage (0, card, defensers->getNextDefenser(NULL, card));
|
||||
damageStack->Add(damage);
|
||||
}else{
|
||||
//SHOULDN'T HAPPEN !
|
||||
}
|
||||
}else{ //Defenser
|
||||
Damage * damage = NEW Damage (mCount,card, card->isDefenser());
|
||||
damageStack->Add(damage);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Player * selecter){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
DamagerDamaged * item = (DamagerDamaged *)mObjects[i];
|
||||
if (item->card == card) return 0;
|
||||
}
|
||||
CardGui * cardg = game->mLayers->playLayer()->getByCard(card);
|
||||
DamagerDamaged * item = NEW DamagerDamaged(cardg, selecter, mCount == 0);
|
||||
Add(item);
|
||||
mCurr = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//Adds a card and all its opponents to the Damagers' list
|
||||
int DamageResolverLayer::addDamager(MTGCardInstance * card, Player * selecter){
|
||||
addIfNotExists(card, selecter);
|
||||
if (card->controller() == game->currentPlayer){ //Attacker
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card);
|
||||
while (defenser != NULL){
|
||||
addIfNotExists(defenser, whoSelectsDamagesDealtBy(defenser));
|
||||
defenser = defensers->getNextDefenser(defenser, card);
|
||||
}
|
||||
}else{ //Defenser
|
||||
MTGInPlay * attackers = game->currentPlayer->game->inPlay;
|
||||
MTGCardInstance * attacker = card->isDefenser();
|
||||
addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker));
|
||||
MTGCardInstance * banding = attacker->banding;
|
||||
if (banding){
|
||||
attacker = attackers->getNextAttacker(NULL);
|
||||
while (attacker != NULL){
|
||||
if (attacker->banding == banding){
|
||||
addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker));
|
||||
}
|
||||
attacker = attackers->getNextAttacker(attacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DamageResolverLayer::initResolve(){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "starting resolve, remainingDamagesStep = %i\n", remainingDamageSteps);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
if (damageStack) return 0;
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
sprintf(buf, "damageStack is NULL, we can resolve \n");
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
currentSource = NULL;
|
||||
currentChoosingPlayer = game->currentPlayer;
|
||||
damageStack = NEW DamageStack(mCount,game);
|
||||
int strike = 0;
|
||||
if (remainingDamageSteps == 2) strike = 1;
|
||||
|
||||
MTGInPlay * attackers = game->currentPlayer->game->inPlay;
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
|
||||
MTGCardInstance * attacker = attackers->getNextAttacker(NULL);
|
||||
while (attacker != NULL){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
sprintf(buf, "attacker : %s \n", attacker->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
if ((!strike && !attacker->has(FIRSTSTRIKE)) || (strike && attacker->has(FIRSTSTRIKE)) || attacker->has(DOUBLESTRIKE)){
|
||||
Player * selecter = whoSelectsDamagesDealtBy(attacker);
|
||||
if (!selecter){
|
||||
addAutoDamageToOpponents(attacker);
|
||||
}else{
|
||||
addDamager(attacker, selecter);
|
||||
}
|
||||
}
|
||||
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker);
|
||||
while (defenser != NULL){
|
||||
if ((!strike && !defenser->has(FIRSTSTRIKE)) || (strike && defenser->has(FIRSTSTRIKE)) || defenser->has(DOUBLESTRIKE)){
|
||||
Player * selecterb = whoSelectsDamagesDealtBy(defenser);
|
||||
if (!selecterb){
|
||||
addAutoDamageToOpponents(defenser);
|
||||
}else{
|
||||
addDamager(defenser, selecterb);
|
||||
}
|
||||
}
|
||||
defenser = defensers->getNextDefenser(defenser, attacker);
|
||||
}
|
||||
attacker = attackers->getNextAttacker(attacker);
|
||||
}
|
||||
|
||||
if (empty()){
|
||||
if (!damageStack->empty()){
|
||||
game->mLayers->stackLayer()->addAction(damageStack);
|
||||
}else{
|
||||
SAFE_DELETE(damageStack);
|
||||
}
|
||||
remainingDamageSteps--;
|
||||
damageStack = NULL;
|
||||
modal = remainingDamageSteps;
|
||||
}else{
|
||||
if (canStopDealDamages()) currentChoosingPlayer = game->opponent();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int DamageResolverLayer::init(){
|
||||
modal = 1;
|
||||
remainingDamageSteps = 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
DamagerDamaged * DamageResolverLayer::findByCard(MTGCardInstance * card){
|
||||
for (int i =0; i < mCount; i++){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[i];
|
||||
if (current->card == card) return current;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Returns 1 if all "compulsory" damages have been assigned for current player
|
||||
int DamageResolverLayer::canStopDealDamages(){
|
||||
for (int i = 0; i < mCount ; i ++){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[i];
|
||||
if (current->damageSelecter==currentChoosingPlayer && current->damageToDeal > 0){
|
||||
MTGCardInstance * card = current->card;
|
||||
if (card->controller() == game->currentPlayer){ //Attacker
|
||||
if (card->has(TRAMPLE)){
|
||||
MTGInPlay * defensers = game->opponent()->game->inPlay;
|
||||
MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card);
|
||||
while (defenser != NULL){
|
||||
DamagerDamaged * _defenser = findByCard(defenser);
|
||||
if (!_defenser->hasLethalDamage()) return 0;
|
||||
defenser = defensers->getNextDefenser(defenser, card);
|
||||
}
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}else{ //Defenser
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DamageResolverLayer::trampleDamage(){
|
||||
for (int i = 0; i < mCount ; i ++){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[i];
|
||||
if (current->damageToDeal > 0){
|
||||
MTGCardInstance * card = current->card;
|
||||
if (card->controller() == game->currentPlayer){ //Attacker
|
||||
if (card->has(TRAMPLE)){
|
||||
Damage * damage = NEW Damage(0, card, game->opponent(), current->damageToDeal);
|
||||
damageStack->Add(damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DamageResolverLayer::resolveDamages(){
|
||||
trampleDamage();
|
||||
for (int i = 0; i < mCount ; i++){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[i];
|
||||
for (int j =0; j < current->mCount ; j++){
|
||||
Damage * damage = NEW Damage(0, current->damages[j]->source, current->damages[j]->target, current->damages[j]->damage);
|
||||
damageStack->Add(damage);
|
||||
}
|
||||
}
|
||||
game->mLayers->stackLayer()->addAction(damageStack);
|
||||
remainingDamageSteps--;
|
||||
resetObjects();
|
||||
damageStack = NULL;
|
||||
modal = remainingDamageSteps;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//a and b are opponents if b is blocking a band in which a belongs or blocking directly a
|
||||
int DamageResolverLayer::isOpponent(DamagerDamaged * a, DamagerDamaged * b){
|
||||
MTGCardInstance * carda = a->card;
|
||||
MTGCardInstance * cardb = b->card;
|
||||
if (cardb->controller() == game->currentPlayer) {//if b is the attacker switch the cards
|
||||
carda = cardb;
|
||||
cardb = a->card;
|
||||
}
|
||||
if (cardb->controller() == game->currentPlayer || carda->controller() == game->opponent()) return 0; //Same team, idiot !
|
||||
|
||||
if (!carda->banding){
|
||||
if (cardb->isDefenser() == carda) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cardb->isDefenser() && cardb->isDefenser()->banding == carda->banding) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DamageResolverLayer::nextPlayer(){
|
||||
if (currentChoosingPlayer == game->currentPlayer){
|
||||
currentChoosingPlayer = game->opponent();
|
||||
if (canStopDealDamages()) resolveDamages();
|
||||
}else{
|
||||
resolveDamages();
|
||||
}
|
||||
|
||||
}
|
||||
void DamageResolverLayer::CheckUserInput(float dt){
|
||||
if (!mCount) return;
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)){
|
||||
if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr];
|
||||
if (!currentSource || !isOpponent(current,currentSource)){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
DamagerDamaged * _current = (DamagerDamaged *) mObjects[i];
|
||||
if (isOpponent(current,_current)){
|
||||
currentSource = _current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentSource){
|
||||
if (currentSource->damageSelecter == currentChoosingPlayer){
|
||||
if (isOpponent(current,currentSource)){
|
||||
if (!currentSource->dealOneDamage(current)){
|
||||
currentSource->removeDamagesTo(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (current->damageSelecter == currentChoosingPlayer){
|
||||
currentSource = current;
|
||||
}
|
||||
}
|
||||
buttonOk = 0;
|
||||
if (canStopDealDamages()) buttonOk = 1;
|
||||
}
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_CROSS)){
|
||||
if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){
|
||||
DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr];
|
||||
if (current->damageSelecter == currentChoosingPlayer){
|
||||
currentSource = current;
|
||||
}
|
||||
}
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_SQUARE)){
|
||||
if (canStopDealDamages()){
|
||||
nextPlayer();
|
||||
//switch to next player or end of selection
|
||||
}
|
||||
}else{
|
||||
PlayGuiObjectController::CheckUserInput(dt);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageResolverLayer::Render(){
|
||||
if (!mCount) return;
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(0 ,0 , SCREEN_WIDTH , SCREEN_HEIGHT , ARGB(200,0,0,0));
|
||||
if (currentChoosingPlayer == game->currentPlayer){
|
||||
mFont->DrawString("Player 1", 0,0);
|
||||
}else{
|
||||
mFont->DrawString("Player 2", 0,0);
|
||||
}
|
||||
if (currentSource){
|
||||
currentSource->RenderBig(10, 20);
|
||||
mFont->DrawString("Current Damager:", 10, 5);
|
||||
}
|
||||
for (int i = 0; i < mCount; i++){
|
||||
((DamagerDamaged *)mObjects[i])->Render(currentChoosingPlayer);
|
||||
}
|
||||
if (mObjects[mCurr]){
|
||||
((DamagerDamaged *)mObjects[mCurr])->Render(currentChoosingPlayer);
|
||||
}
|
||||
|
||||
|
||||
if (buttonOk){
|
||||
mFont->DrawString("Damages Assigned, Click Square to Continue", 250, 5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/DamagerDamaged.h"
|
||||
|
||||
|
||||
|
||||
|
||||
DamagerDamaged::DamagerDamaged(CardGui * cardg, Player * _damageSelecter, bool _hasFocus):CardGui(0, cardg->card,cardg->defaultHeight,cardg->x,cardg->y, _hasFocus){
|
||||
mCount = 0;
|
||||
damageSelecter = _damageSelecter;
|
||||
damageToDeal = card->power;
|
||||
}
|
||||
|
||||
DamagerDamaged::~DamagerDamaged(){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
delete damages[i];
|
||||
damages[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int DamagerDamaged::sumDamages(){
|
||||
int total = 0;
|
||||
for (int i = 0; i < mCount; i++){
|
||||
total += damages[i]->damage;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
int DamagerDamaged::hasLethalDamage(){
|
||||
if (sumDamages() >= card->toughness) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DamagerDamaged::dealOneDamage(DamagerDamaged * target){
|
||||
if (!damageToDeal) return 0;
|
||||
damageToDeal--;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "==========\n%s can still deal %i damages\n=============\n", card->getName(), damageToDeal);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
return target->addDamage(1, this);
|
||||
}
|
||||
|
||||
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){
|
||||
for (int i = 0; i < mCount; i++){
|
||||
if (damages[i]->source == source->card){
|
||||
int damage = damages[i]->damage;
|
||||
delete(damages[i]);
|
||||
damages[i] = NULL;
|
||||
damages[i] = damages[mCount-1];
|
||||
mCount--;
|
||||
return damage;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DamagerDamaged::Render(Player * currentPlayer){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetBase(0);
|
||||
mFont->SetScale(0.75);
|
||||
CardGui::Render();
|
||||
char buf[4096];
|
||||
|
||||
if (currentPlayer != damageSelecter){
|
||||
if (hasLethalDamage()){
|
||||
mFont->DrawString("X",x,y);
|
||||
}
|
||||
mFont->SetColor(ARGB(255,255,0,0));
|
||||
sprintf(buf, "%i", sumDamages());
|
||||
mFont->DrawString(buf,x+5, y+5);
|
||||
}else{
|
||||
mFont->SetColor(ARGB(255,0,0,255));
|
||||
sprintf(buf, "%i", damageToDeal);
|
||||
mFont->DrawString(buf,x+5, y+5);
|
||||
}
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "../include/DeckDataWrapper.h"
|
||||
#include "../include/MTGDeck.h"
|
||||
|
||||
DeckDataWrapper::DeckDataWrapper(MTGDeck * deck){
|
||||
parent = deck;
|
||||
for (int i = 0; i <= MTG_NB_COLORS; i++){
|
||||
colors[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < deck->totalCards(); i++){
|
||||
MTGCard * card = deck->_(i);
|
||||
Add(card);
|
||||
}
|
||||
currentposition = 0;
|
||||
currentColor = -1;
|
||||
}
|
||||
|
||||
void DeckDataWrapper::save(){
|
||||
parent->removeAll();
|
||||
map<MTGCard *,int,Cmp1>::iterator it;
|
||||
for ( it=cards.begin() ; it != cards.end(); it++ ){
|
||||
MTGCard * current = (*it).first;
|
||||
for (int i = 0; i < (*it).second; i++){
|
||||
parent->add(current);
|
||||
}
|
||||
}
|
||||
parent->save();
|
||||
}
|
||||
|
||||
|
||||
DeckDataWrapper::~DeckDataWrapper(){
|
||||
SAFE_DELETE(parent);
|
||||
}
|
||||
|
||||
void DeckDataWrapper::updateCounts(MTGCard * card, int removed){
|
||||
if (!card){
|
||||
for (int i = 0; i < MTG_NB_COLORS+1; i++){
|
||||
colors[i] = 0;
|
||||
}
|
||||
map<MTGCard *,int,Cmp1>::iterator it;
|
||||
for ( it=cards.begin() ; it != cards.end(); it++ ){
|
||||
MTGCard * current = (*it).first;
|
||||
colors[MTG_NB_COLORS] += (*it).second;
|
||||
for (int i = 0; i < MTG_NB_COLORS; i++){
|
||||
if (current->hasColor(i)) colors[i]+=(*it).second;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int increment = 1;
|
||||
if (removed) increment = -1;
|
||||
colors[MTG_NB_COLORS] += increment;
|
||||
for (int i = 0; i < MTG_NB_COLORS; i++){
|
||||
if (card->hasColor(i)) colors[i]+=increment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DeckDataWrapper::Add(MTGCard * card){
|
||||
if(cards.find(card) == cards.end()){
|
||||
cards[card] = 1;
|
||||
}else{
|
||||
cards[card]++;
|
||||
}
|
||||
updateCounts(card);
|
||||
return cards[card];
|
||||
}
|
||||
|
||||
int DeckDataWrapper::Remove(MTGCard * card){
|
||||
if(cards.find(card) == cards.end() || cards[card] == 0) return 0;
|
||||
cards[card]--;
|
||||
updateCounts(card,1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
MTGCard * DeckDataWrapper::getNext(MTGCard * previous, int color){
|
||||
map<MTGCard *,int,Cmp1>::iterator it;
|
||||
|
||||
it = cards.find(previous);
|
||||
int found = 0;
|
||||
|
||||
while(1){
|
||||
if (it == cards.end()){
|
||||
it = cards.begin();
|
||||
}else{
|
||||
it++;
|
||||
}
|
||||
if (it == cards.end()) return NULL;
|
||||
MTGCard * card = (*it).first;
|
||||
if (card == previous) return NULL;
|
||||
if ((*it).second >0 && (color ==-1 || card->hasColor(color))){
|
||||
return card;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTGCard * DeckDataWrapper::getPrevious(MTGCard * next, int color){
|
||||
map<MTGCard *,int,Cmp1>::iterator it;
|
||||
it = cards.find(next);
|
||||
int found = 0;
|
||||
|
||||
while(1){
|
||||
if (it == cards.begin()){
|
||||
it = cards.end();
|
||||
}else{
|
||||
it--;
|
||||
}
|
||||
if (it == cards.end()) return NULL;
|
||||
MTGCard * card = (*it).first;
|
||||
if (card == next) return NULL;
|
||||
if ((*it).second >0 && (color ==-1 || card->hasColor(color))){
|
||||
return card;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeckDataWrapper::updateCurrentPosition(MTGCard * currentCard, int color){
|
||||
currentposition = 0;
|
||||
MTGCard * next = getNext(NULL,color);
|
||||
while (next){
|
||||
currentposition+=cards[next];
|
||||
if (next == currentCard){
|
||||
next = NULL;
|
||||
}else{
|
||||
next = getNext(next,color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DeckDataWrapper::getCount(int color){
|
||||
if (color == -1) return colors[MTG_NB_COLORS];
|
||||
return colors[color];
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/DuelLayers.h"
|
||||
#include "../include/MTGRules.h"
|
||||
#include "../include/DamageResolverLayer.h"
|
||||
|
||||
|
||||
|
||||
void DuelLayers::init(){
|
||||
|
||||
|
||||
//0 Stack Layer
|
||||
ActionStack * mActionStack = NEW ActionStack(0, GameObserver::GetInstance());
|
||||
|
||||
//Damage Resolver
|
||||
DamageResolverLayer * mDamageResolver = NEW DamageResolverLayer(1, GameObserver::GetInstance());
|
||||
|
||||
//1 Action Layer
|
||||
GuiLayer * actionLayer = NEW ActionLayer(2, GameObserver::GetInstance());
|
||||
MTGGamePhase * phaseManager = NEW MTGGamePhase(actionLayer->getMaxId());
|
||||
actionLayer->Add(phaseManager);
|
||||
//Add Magic Specific Rules
|
||||
actionLayer->Add(NEW MTGAttackRule(-1));
|
||||
actionLayer->Add(NEW MTGBlockRule(-1));
|
||||
actionLayer->Add(NEW MTGLegendRule(-1));
|
||||
actionLayer->Add(NEW MTGPersistRule(-1));
|
||||
|
||||
//2 Hand Layer
|
||||
MTGGuiHand * mGuiHand = NEW MTGGuiHand(3, GameObserver::GetInstance());
|
||||
|
||||
//3 Game
|
||||
MTGGuiPlay * play = NEW MTGGuiPlay(4, GameObserver::GetInstance());
|
||||
|
||||
Add(mActionStack);
|
||||
Add(mDamageResolver);
|
||||
Add(actionLayer);
|
||||
Add(mGuiHand);
|
||||
Add(play);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ActionStack * DuelLayers::stackLayer(){
|
||||
return ((ActionStack *) (objects[0]));
|
||||
}
|
||||
|
||||
DamageResolverLayer * DuelLayers::combatLayer(){
|
||||
return ((DamageResolverLayer *) (objects[1]));
|
||||
}
|
||||
|
||||
ActionLayer * DuelLayers::actionLayer(){
|
||||
return ((ActionLayer *) (objects[2]));
|
||||
}
|
||||
|
||||
MTGGuiHand * DuelLayers::handLayer(){
|
||||
return ((MTGGuiHand *) (objects[3]));
|
||||
}
|
||||
MTGGuiPlay * DuelLayers::playLayer(){
|
||||
return ((MTGGuiPlay *) (objects[4]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
|
||||
#include "../include/debug.h"
|
||||
#include <JGE.h>
|
||||
#include <JRenderer.h>
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
#else
|
||||
#include <pspfpu.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "../include/GameApp.h"
|
||||
#include "../include/Subtypes.h"
|
||||
#include "../include/GameStateDeckViewer.h"
|
||||
#include "../include/GameStateMenu.h"
|
||||
#include "../include/GameStateDuel.h"
|
||||
#include "../include/GameStateOptions.h"
|
||||
#include "../include/GameStateShop.h"
|
||||
|
||||
|
||||
const char * const GameState::menuTexts[]= {"--NEW--","Deck 1", "Deck 2", "Deck 3", "Deck 4", "Deck 5", "Deck 6"} ;
|
||||
JResourceManager* GameApp::CommonRes = NEW JResourceManager();
|
||||
hgeParticleSystem* GameApp::Particles[] = {NULL,NULL,NULL,NULL,NULL,NULL};
|
||||
int GameApp::HasMusic = 1;
|
||||
|
||||
GameState::GameState(GameApp* parent): mParent(parent)
|
||||
{
|
||||
mEngine = JGE::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
GameApp::GameApp(): JApp()
|
||||
{
|
||||
mScreenShotCount = 0;
|
||||
|
||||
for (int i=0; i < MAX_STATE ; i++)
|
||||
mGameStates[i] = NULL;
|
||||
|
||||
mShowDebugInfo = false;
|
||||
players[0] = 0;
|
||||
players[1] = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
GameApp::~GameApp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GameApp::Create()
|
||||
{
|
||||
#if defined (WIN32)
|
||||
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||
#elif not defined (LINUX)
|
||||
pspfpu_set_enable(0); //disable FPU Exceptions until we find where the FPU errors come from
|
||||
#endif
|
||||
//_CrtSetBreakAlloc(368);
|
||||
LOG("starting Game");
|
||||
|
||||
//Test for Music files presence
|
||||
std::ifstream file("Res/sound/Track0.mp3");
|
||||
if(file){
|
||||
file.close();
|
||||
}else{
|
||||
HasMusic = 0;
|
||||
}
|
||||
std::ifstream file2("Res/sound/Track1.mp3");
|
||||
if(file2){
|
||||
file2.close();
|
||||
}else{
|
||||
HasMusic = 0;
|
||||
}
|
||||
|
||||
|
||||
CommonRes->CreateTexture("graphics/menuicons.png");
|
||||
//Creating thes quad in this specific order allows us to have them in the correct order to call them by integer id
|
||||
CommonRes->CreateQuad("c_artifact", "graphics/menuicons.png", 10 + 6*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_green", "graphics/menuicons.png", 10 + 0*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_blue", "graphics/menuicons.png", 10 + 1*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_red", "graphics/menuicons.png", 10 + 3*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_black", "graphics/menuicons.png", 10 + 2*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_white", "graphics/menuicons.png", 10 + 4*32, 32, 32, 32);
|
||||
CommonRes->CreateQuad("c_land", "graphics/menuicons.png", 10 + 5*32, 32, 32, 32);
|
||||
|
||||
|
||||
CommonRes->CreateTexture("sets/back.jpg");
|
||||
CommonRes->CreateQuad("back", "sets/back.jpg", 0, 0, 200, 285);
|
||||
CommonRes->CreateTexture("sets/back_thumb.jpg");
|
||||
CommonRes->CreateQuad("back_thumb", "sets/back_thumb.jpg", 0, 0, 45, 64);
|
||||
|
||||
CommonRes->CreateTexture("graphics/particles.png");
|
||||
CommonRes->CreateQuad("particles", "graphics/particles.png", 0, 0, 32, 32);
|
||||
CommonRes->GetQuad("particles")->SetHotSpot(16,16);
|
||||
|
||||
CommonRes->LoadJLBFont("graphics/f3",16);
|
||||
CommonRes->LoadJLBFont("graphics/magic",16);
|
||||
|
||||
|
||||
//CommonRes->CreateTexture("graphics/interrupt.png");
|
||||
//CommonRes->CreateQuad("interrupt", "graphics/interrupt.png", 0, 0, 256, 128);
|
||||
|
||||
cache = NEW TexturesCache();
|
||||
collection = NEW MTGAllCards(cache);
|
||||
|
||||
|
||||
Particles[0] = NEW hgeParticleSystem("graphics/particle1.psi", CommonRes->GetQuad("particles"));
|
||||
Particles[1] = NEW hgeParticleSystem("graphics/particle2.psi", CommonRes->GetQuad("particles"));
|
||||
Particles[2] = NEW hgeParticleSystem("graphics/particle3.psi", CommonRes->GetQuad("particles"));
|
||||
Particles[3] = NEW hgeParticleSystem("graphics/particle4.psi", CommonRes->GetQuad("particles"));
|
||||
Particles[4] = NEW hgeParticleSystem("graphics/particle5.psi", CommonRes->GetQuad("particles"));
|
||||
Particles[5] = NEW hgeParticleSystem("graphics/particle7.psi", CommonRes->GetQuad("particles"));
|
||||
|
||||
mGameStates[GAME_STATE_DECK_VIEWER] = NEW GameStateDeckViewer(this);
|
||||
mGameStates[GAME_STATE_DECK_VIEWER]->Create();
|
||||
|
||||
mGameStates[GAME_STATE_MENU] = NEW GameStateMenu(this);
|
||||
mGameStates[GAME_STATE_MENU]->Create();
|
||||
|
||||
|
||||
mGameStates[GAME_STATE_DUEL] = NEW GameStateDuel(this);
|
||||
mGameStates[GAME_STATE_DUEL]->Create();
|
||||
|
||||
mGameStates[GAME_STATE_SHOP] = NEW GameStateShop(this);
|
||||
mGameStates[GAME_STATE_SHOP]->Create();
|
||||
|
||||
mGameStates[GAME_STATE_OPTIONS] = NEW GameStateOptions(this);
|
||||
mGameStates[GAME_STATE_OPTIONS]->Create();
|
||||
|
||||
|
||||
|
||||
//mGameStates[GAME_STATE_GAME] = NEW GameStateGAME(this);
|
||||
|
||||
mCurrentState = NULL;
|
||||
mNextState = mGameStates[GAME_STATE_MENU];
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameApp::LoadGameStates()
|
||||
{
|
||||
|
||||
//mGameStates[GAME_STATE_MENU]->Create();
|
||||
//mGameStates[GAME_STATE_GAME]->Create();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameApp::Destroy()
|
||||
{
|
||||
LOG("==Destroying GameApp==");
|
||||
for (int i=GAME_STATE_MENU;i<=MAX_STATE-1;i++)
|
||||
{
|
||||
if (mGameStates[i]){
|
||||
mGameStates[i]->Destroy();
|
||||
delete mGameStates[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i= 0; i < 6; i++){
|
||||
delete Particles[i];
|
||||
}
|
||||
|
||||
if (collection){
|
||||
collection->destroyAllCards();
|
||||
delete collection;
|
||||
}
|
||||
if (cache) delete cache;
|
||||
|
||||
if (CommonRes) delete CommonRes;
|
||||
|
||||
GameOptions::Destroy();
|
||||
|
||||
if (Subtypes::subtypesList) delete Subtypes::subtypesList;
|
||||
if (MtgSets::SetsList) delete MtgSets::SetsList;
|
||||
LOG("==Destroying GameApp Successful==");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GameApp::Update()
|
||||
{
|
||||
|
||||
JGE* mEngine = JGE::GetInstance();
|
||||
if (mEngine->GetButtonState(PSP_CTRL_START) && mEngine->GetButtonClick(PSP_CTRL_TRIANGLE))
|
||||
{
|
||||
char s[80];
|
||||
sprintf(s, "ms0:/psp/photo/MTG%d.png", mScreenShotCount++);
|
||||
JRenderer::GetInstance()->ScreenShot(s);
|
||||
}
|
||||
//Exit when START and X ARE PRESSED SIMULTANEOUSLY
|
||||
if (mEngine->GetButtonState(PSP_CTRL_START) && mEngine->GetButtonState(PSP_CTRL_CROSS)){
|
||||
mEngine->End();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float dt = mEngine->GetDelta();
|
||||
if (dt > 35.0f) // min 30 FPS ;)
|
||||
dt = 35.0f;
|
||||
|
||||
if (mCurrentState != NULL)
|
||||
mCurrentState->Update(dt);
|
||||
|
||||
if (mNextState != NULL)
|
||||
{
|
||||
if (mCurrentState != NULL)
|
||||
mCurrentState->End();
|
||||
|
||||
mCurrentState = mNextState;
|
||||
mCurrentState->Start();
|
||||
|
||||
mNextState = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameApp::Render()
|
||||
{
|
||||
|
||||
if (mCurrentState != NULL)
|
||||
{
|
||||
mCurrentState->Render();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void GameApp::SetNextState(int state)
|
||||
{
|
||||
mNextState = mGameStates[state];
|
||||
}
|
||||
|
||||
void GameApp::Pause(){
|
||||
|
||||
}
|
||||
|
||||
void GameApp::Resume(){
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//-------------------------------------------------------------------------------------
|
||||
//
|
||||
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
|
||||
//
|
||||
// Licensed under the BSD license, see LICENSE in JGE root for details.
|
||||
//
|
||||
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GAMEAPP_H_
|
||||
#define _GAMEAPP_H_
|
||||
|
||||
#include <JApp.h>
|
||||
|
||||
class GameApp: public JApp
|
||||
{
|
||||
|
||||
public:
|
||||
GameApp();
|
||||
virtual ~GameApp();
|
||||
virtual void Create();
|
||||
virtual void Destroy();
|
||||
virtual void Update();
|
||||
virtual void Render();
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
//-------------------------------------------------------------------------------------
|
||||
//
|
||||
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
|
||||
//
|
||||
// Licensed under the BSD license, see LICENSE in JGE root for details.
|
||||
//
|
||||
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
#include "../include/debug.h"
|
||||
#include <string.h>
|
||||
#include <JGameLauncher.h>
|
||||
|
||||
#include "../include/GameApp.h"
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
JApp* JGameLauncher::GetGameApp()
|
||||
{
|
||||
return NEW GameApp();
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
char *JGameLauncher::GetName()
|
||||
{
|
||||
return strdup("Wagic");
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
u32 JGameLauncher::GetInitFlags()
|
||||
{
|
||||
return JINIT_FLAG_NORMAL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,469 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GameObserver.h"
|
||||
|
||||
#include "../include/GameOptions.h"
|
||||
#include "../include/ConstraintResolver.h"
|
||||
#include "../include/CardGui.h"
|
||||
#include "../include/Damage.h"
|
||||
#include "../include/DamageResolverLayer.h"
|
||||
|
||||
#include <JRenderer.h>
|
||||
|
||||
GameObserver * GameObserver::mInstance = NULL;
|
||||
|
||||
|
||||
GameObserver* GameObserver::GetInstance()
|
||||
{
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
void GameObserver::EndInstance()
|
||||
{
|
||||
|
||||
SAFE_DELETE(mInstance);
|
||||
}
|
||||
|
||||
void GameObserver::Init(Player * _players[], int _nbplayers){
|
||||
mInstance = NEW GameObserver(_players, _nbplayers);
|
||||
mInstance->mLayers = NEW DuelLayers();
|
||||
mInstance->mLayers->init();
|
||||
}
|
||||
|
||||
|
||||
GameObserver::GameObserver(Player * _players[], int _nb_players){
|
||||
int i;
|
||||
|
||||
for (i =0; i < _nb_players;i ++){
|
||||
players[i] = _players[i];
|
||||
}
|
||||
currentPlayer = players[0];
|
||||
currentActionPlayer = currentPlayer;
|
||||
isInterrupting = NULL;
|
||||
currentPlayerId = 0;
|
||||
nbPlayers = _nb_players;
|
||||
currentRound = 1;
|
||||
currentGamePhase = -1;
|
||||
targetChooser = NULL;
|
||||
cardWaitingForTargets = NULL;
|
||||
reaction = 0;
|
||||
gameOver = NULL;
|
||||
}
|
||||
|
||||
void GameObserver::setGamePhaseManager(MTGGamePhase * _phases){
|
||||
gamePhaseManager = _phases;
|
||||
}
|
||||
|
||||
int GameObserver::getCurrentGamePhase(){
|
||||
return currentGamePhase;
|
||||
}
|
||||
|
||||
|
||||
Player * GameObserver::opponent(){
|
||||
int index = (currentPlayerId+1)%nbPlayers;
|
||||
return players[index];
|
||||
}
|
||||
|
||||
int GameObserver::enteringPhase(int phase){
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameObserver::nextPlayer(){
|
||||
currentPlayerId = (currentPlayerId+1)%nbPlayers;
|
||||
currentPlayer = players[currentPlayerId];
|
||||
currentActionPlayer = currentPlayer;
|
||||
currentPlayer->canPutLandsIntoPlay = 1; //TODO more useful function
|
||||
}
|
||||
void GameObserver::nextGamePhase(){
|
||||
currentGamePhase++;
|
||||
|
||||
//manaBurn
|
||||
if (currentGamePhase == MTG_PHASE_UNTAP ||
|
||||
currentGamePhase == MTG_PHASE_FIRSTMAIN ||
|
||||
currentGamePhase == MTG_PHASE_COMBATBEGIN ||
|
||||
currentGamePhase == MTG_PHASE_SECONDMAIN ||
|
||||
currentGamePhase == MTG_PHASE_ENDOFTURN
|
||||
){
|
||||
currentPlayer->manaBurn();
|
||||
}
|
||||
|
||||
//Next Player ?
|
||||
if (currentGamePhase > MTG_PHASE_CLEANUP){
|
||||
//Auto Hand cleaning, in case the player didn't do it himself
|
||||
while(currentPlayer->game->hand->nb_cards > 7){
|
||||
currentPlayer->game->putInGraveyard(currentPlayer->game->hand->cards[0]);
|
||||
}
|
||||
mLayers->stackLayer()->garbageCollect(); //clean stack history for this turn;
|
||||
nextPlayer();
|
||||
currentGamePhase = MTG_PHASE_UNTAP;
|
||||
}
|
||||
|
||||
//Phase Specific actions
|
||||
switch(currentGamePhase){
|
||||
case MTG_PHASE_UNTAP:
|
||||
cleanupPhase();
|
||||
untapPhase();
|
||||
break;
|
||||
case MTG_PHASE_DRAW:
|
||||
mLayers->stackLayer()->addDraw(currentPlayer,1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int GameObserver::cancelCurrentAction(){
|
||||
SAFE_DELETE(targetChooser);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GameObserver::userRequestNextGamePhase(){
|
||||
if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return;
|
||||
if (getCurrentTargetChooser()) return;
|
||||
if (mLayers->combatLayer()->remainingDamageSteps) return;
|
||||
//TODO CHECK POSSIBILITY
|
||||
if (opponent()->isAI() || GameOptions::GetInstance()->values[OPTIONS_INTERRUPTATENDOFPHASE_OFFSET+currentGamePhase]){
|
||||
mLayers->stackLayer()->AddNextGamePhase();
|
||||
}else{
|
||||
nextGamePhase();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GameObserver::startGame(int shuffle, int draw){
|
||||
int i;
|
||||
for (i=0; i<nbPlayers; i++){
|
||||
players[i]->game->initGame(shuffle, draw);
|
||||
}
|
||||
currentGamePhase = MTG_PHASE_FIRSTMAIN;
|
||||
}
|
||||
|
||||
void GameObserver::addObserver(MTGAbility * observer){
|
||||
mLayers->actionLayer()->Add(observer);
|
||||
}
|
||||
|
||||
|
||||
void GameObserver::removeObserver(ActionElement * observer){
|
||||
if (observer){
|
||||
observer->destroy();
|
||||
}else{
|
||||
//TODO log error
|
||||
}
|
||||
mLayers->actionLayer()->Remove(observer);
|
||||
}
|
||||
|
||||
GameObserver::~GameObserver(){
|
||||
LOG("==Destroying GameObserver==");
|
||||
SAFE_DELETE(targetChooser);
|
||||
SAFE_DELETE(mLayers);
|
||||
LOG("==GameObserver Destroyed==");
|
||||
|
||||
}
|
||||
|
||||
void GameObserver::Update(float dt){
|
||||
Player * player = currentPlayer;
|
||||
if (currentGamePhase == MTG_PHASE_COMBATBLOCKERS){
|
||||
player = opponent();
|
||||
}else if (currentGamePhase == MTG_PHASE_COMBATDAMAGE){
|
||||
DamageResolverLayer * drl = mLayers->combatLayer();
|
||||
if (drl->currentChoosingPlayer && drl->mCount) player = drl->currentChoosingPlayer;
|
||||
}
|
||||
currentActionPlayer = player;
|
||||
if (isInterrupting) player = isInterrupting;
|
||||
mLayers->Update(dt,player);
|
||||
stateEffects();
|
||||
oldGamePhase = currentGamePhase;
|
||||
|
||||
}
|
||||
|
||||
//applies damage to creatures after updates
|
||||
//Players life test
|
||||
void GameObserver::stateEffects(){
|
||||
for (int i =0; i < 2; i++){
|
||||
MTGGameZone * zone = players[i]->game->inPlay;
|
||||
for (int j = zone->nb_cards-1 ; j>=0; j--){
|
||||
MTGCardInstance * card = zone->cards[j];
|
||||
card->afterDamage();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i =0; i < 2; i++){
|
||||
if (players[i]->life <= 0) gameOver = players[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameObserver::Render(){
|
||||
mLayers->Render();
|
||||
if (targetChooser || mLayers->actionLayer()->isWaitingForAnswer()){
|
||||
JRenderer::GetInstance()->DrawRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(255,255,0,0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameObserver::nextStep(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void GameObserver::ButtonPressed (int controllerId, PlayGuiObject * _object){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Click\n");
|
||||
#endif
|
||||
int id = _object->GetId();
|
||||
if (id >=0){
|
||||
MTGCardInstance * card = ((CardGui *)_object)->card;
|
||||
cardClick(card, card);
|
||||
}
|
||||
//if (id>= -6 && id <= -3){
|
||||
if (id== -5 || id == -3){ //TODO libraries ???
|
||||
GuiGameZone * zone = (GuiGameZone *)_object;
|
||||
zone->toggleDisplay();
|
||||
}
|
||||
if (id == -1 || id == -2){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Click Player !\n");
|
||||
#endif
|
||||
cardClick(NULL, ((GuiAvatar *)_object)->player);
|
||||
}
|
||||
}
|
||||
|
||||
void GameObserver::stackObjectClicked(Interruptible * action){
|
||||
if (targetChooser != NULL){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("target chooser ok \n");
|
||||
#endif
|
||||
int result = targetChooser->toggleTarget(action);
|
||||
if (result == TARGET_OK_FULL){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("target chooser Full \n");
|
||||
#endif
|
||||
cardClick(cardWaitingForTargets);
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
reaction = mLayers->actionLayer()->isReactingToTargetClick(action);
|
||||
if (reaction == -1) mLayers->actionLayer()->reactToTargetClick(action);
|
||||
}
|
||||
}
|
||||
|
||||
void GameObserver::cardClick (MTGCardInstance * card, Targetable * object){
|
||||
LOG("==GameObserver::cardClick");
|
||||
if (card) {LOG(card->getName())};
|
||||
Player * clickedPlayer = NULL;
|
||||
if (!card) clickedPlayer = ((Player *)object);
|
||||
if (targetChooser != NULL){
|
||||
int result;
|
||||
if (card) {
|
||||
if (card == cardWaitingForTargets){
|
||||
LOG("attempt to close targetting");
|
||||
int _result = targetChooser->ForceTargetListReady();
|
||||
if (_result){
|
||||
result = TARGET_OK_FULL;
|
||||
}else{
|
||||
|
||||
LOG("...but we cant!\n");
|
||||
result = targetChooser->targetsReadyCheck();
|
||||
}
|
||||
}else{
|
||||
result = targetChooser->toggleTarget(card);
|
||||
}
|
||||
}else{
|
||||
result = targetChooser->toggleTarget(clickedPlayer);
|
||||
}
|
||||
if (result == TARGET_OK_FULL){
|
||||
card = cardWaitingForTargets;
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (card){
|
||||
reaction = mLayers->actionLayer()->isReactingToClick(card);
|
||||
if (reaction == -1) mLayers->actionLayer()->reactToClick(card);
|
||||
}else{
|
||||
reaction = mLayers->actionLayer()->isReactingToTargetClick(object);
|
||||
if (reaction == -1) mLayers->actionLayer()->reactToTargetClick(object);
|
||||
}
|
||||
|
||||
if (reaction != -1){
|
||||
if (!card) return;
|
||||
if (currentlyActing()->game->hand->hasCard(card)){
|
||||
//Current player's hand
|
||||
if (canPutInPlay(card)){
|
||||
putInPlay(card);
|
||||
if (card->hasType("land")){
|
||||
currentPlayer->canPutLandsIntoPlay--;
|
||||
}
|
||||
}else if (currentPlayer->game->hand->hasCard(card)){ //Current player's hand
|
||||
if (currentGamePhase == MTG_PHASE_CLEANUP && currentPlayer->game->hand->nb_cards > 7){
|
||||
currentPlayer->game->putInGraveyard(card);
|
||||
}
|
||||
}
|
||||
}else if (reaction){
|
||||
if (reaction == 1){
|
||||
mLayers->actionLayer()->reactToClick(card);
|
||||
}else{
|
||||
mLayers->actionLayer()->setMenuObject(object);
|
||||
}
|
||||
}else if (card->isTapped() && card->controller() == currentPlayer){
|
||||
int a = ConstraintResolver::untap(this, card);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
TargetChooser * GameObserver::getCurrentTargetChooser(){
|
||||
TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser();
|
||||
if (_tc) return _tc;
|
||||
return targetChooser;
|
||||
}
|
||||
|
||||
//Check if it is possible to put a card into play
|
||||
//TODO : improve according to spells in game...
|
||||
int GameObserver::canPutInPlay(MTGCardInstance * card){
|
||||
Player * player = currentlyActing();
|
||||
LOG("CANPUTINPLAY- check if card belongs to current player\n");
|
||||
if (!player->game->hand->hasCard(card)) return 0;
|
||||
LOG("CANPUTINPLAY- check if card is land or can be played\n");
|
||||
if (card->hasType("land")){
|
||||
LOG("CANPUTINPLAY- card is land - check if can be played\n");
|
||||
if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (currentGamePhase == MTG_PHASE_FIRSTMAIN || currentGamePhase == MTG_PHASE_SECONDMAIN)){
|
||||
LOG("CANPUTINPLAY- Land, ok\n");
|
||||
return 1;
|
||||
}
|
||||
}else if ((card->hasType("instant")) || card->has(FLASH) || (player == currentPlayer && (currentGamePhase == MTG_PHASE_FIRSTMAIN || currentGamePhase == MTG_PHASE_SECONDMAIN))){
|
||||
LOG("CANPUTINPLAY- correct time to play\n");
|
||||
if (checkManaCost(card)){
|
||||
LOG("CANPUTINPLAY- ManaCost ok\n");
|
||||
if (targetListIsSet(card)){
|
||||
#ifdef LOG
|
||||
LOG("CANPUTINPLAY- Targets chosen -> OK\n");
|
||||
#endif
|
||||
return 1;
|
||||
}else{
|
||||
#ifdef LOG
|
||||
LOG("CANPUTINPLAY- Targets not chosen yet\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void GameObserver::putInPlay(MTGCardInstance * card){
|
||||
Player * player = currentlyActing();
|
||||
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
|
||||
player->getManaPool()->pay(card->getManaCost());
|
||||
ManaCost * spellCost = previousManaPool->Diff(player->getManaPool());
|
||||
delete previousManaPool;
|
||||
if (card->hasType("land")){
|
||||
Spell * spell = NEW Spell(card);
|
||||
player->game->putInZone(card, player->game->hand, player->game->stack);
|
||||
spell->resolve();
|
||||
delete spellCost;
|
||||
delete spell;
|
||||
}else{
|
||||
if (targetChooser){
|
||||
mLayers->stackLayer()->addSpell(card,targetChooser->targets,targetChooser->cursor, spellCost);
|
||||
delete targetChooser;
|
||||
targetChooser = NULL;
|
||||
}else{
|
||||
mLayers->stackLayer()->addSpell(card,NULL,0, spellCost);
|
||||
}
|
||||
player->game->putInZone(card, player->game->hand, player->game->stack);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Returns true if the card is in one of the player's play zone */
|
||||
int GameObserver::isInPlay(MTGCardInstance * card){
|
||||
for (int i = 0; i < 2; i++){
|
||||
if (players[i]->game->isInPlay(card)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameObserver::draw(){
|
||||
//TODO checks to allow multiple draw, or no draw, etc...
|
||||
currentPlayer->game->drawFromLibrary();
|
||||
}
|
||||
|
||||
void GameObserver::cleanupPhase(){
|
||||
currentPlayer->cleanupPhase();
|
||||
opponent()->cleanupPhase();
|
||||
}
|
||||
|
||||
void GameObserver::untapPhase(){
|
||||
currentPlayer->inPlay()->untapAll();
|
||||
}
|
||||
|
||||
|
||||
int GameObserver::isACreature(MTGCardInstance * card){
|
||||
return card->isACreature();
|
||||
}
|
||||
|
||||
|
||||
Player * GameObserver::currentlyActing(){
|
||||
if (isInterrupting) return isInterrupting;
|
||||
return currentActionPlayer;
|
||||
}
|
||||
|
||||
int GameObserver::tryToTapOrUntap(MTGCardInstance * card){
|
||||
|
||||
int reaction = mLayers->actionLayer()->isReactingToClick(card);
|
||||
if (reaction){
|
||||
if (reaction == 1){
|
||||
mLayers->actionLayer()->reactToClick(card);
|
||||
}else{
|
||||
//TODO, what happens when several abilities react to the click ?
|
||||
}
|
||||
return reaction;
|
||||
}else{
|
||||
if (card->isTapped() && card->controller() == currentPlayer){
|
||||
int a = ConstraintResolver::untap(this, card);
|
||||
return a;
|
||||
}else{
|
||||
//TODO Check Spells
|
||||
//card->tap();
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO CORRECT THIS MESS
|
||||
int GameObserver::targetListIsSet(MTGCardInstance * card){
|
||||
if (targetChooser == NULL){
|
||||
TargetChooserFactory tcf;
|
||||
targetChooser = tcf.createTargetChooser(card);
|
||||
cardWaitingForTargets = card;
|
||||
if (targetChooser == NULL){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return (targetChooser->targetListSet());
|
||||
}
|
||||
|
||||
|
||||
int GameObserver::checkManaCost(MTGCardInstance * card){
|
||||
ManaCost * playerMana = currentlyActing()->getManaPool();
|
||||
ManaCost * cost = card->getManaCost();
|
||||
if (playerMana->canAfford(cost)){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GameOptions.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
GameOptions* GameOptions::mInstance = NULL;
|
||||
|
||||
GameOptions * GameOptions::GetInstance(){
|
||||
if (mInstance == NULL)
|
||||
mInstance = NEW GameOptions();
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
GameOptions::GameOptions(){
|
||||
for(int i = 0; i < MAX_OPTIONS; i++){
|
||||
values[i] = 0;
|
||||
}
|
||||
load();
|
||||
}
|
||||
|
||||
int GameOptions::load(){
|
||||
std::ifstream file(OPTIONS_SAVEFILE);
|
||||
std::string s;
|
||||
if(file){
|
||||
for (int i = 0; i < MAX_OPTIONS; i++){
|
||||
if(std::getline(file,s)){
|
||||
values[i] = atoi(s.c_str());
|
||||
}else{
|
||||
//TODO error management
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GameOptions::save(){
|
||||
std::ofstream file(OPTIONS_SAVEFILE);
|
||||
char writer[10];
|
||||
if (file){
|
||||
for (int i = 0; i < MAX_OPTIONS; i++){
|
||||
sprintf(writer,"%i\n", values[i]);
|
||||
file<<writer;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
GameOptions::~GameOptions(){
|
||||
}
|
||||
|
||||
void GameOptions::Destroy(){
|
||||
if (mInstance){
|
||||
delete mInstance;
|
||||
mInstance = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GameStateDuel.h"
|
||||
#include "../include/utils.h"
|
||||
#include "../include/AIPlayer.h"
|
||||
#include "../include/PlayerData.h"
|
||||
|
||||
#ifdef TESTSUITE
|
||||
#include "../include/TestSuiteAI.h"
|
||||
#endif
|
||||
|
||||
GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) {
|
||||
for (int i = 0; i<2; i ++){
|
||||
deck[i]=NULL;
|
||||
mPlayers[i]=NULL;
|
||||
}
|
||||
|
||||
game = NULL;
|
||||
deckmenu = NULL;
|
||||
menu = NULL;
|
||||
#ifdef TESTSUITE
|
||||
testSuite = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
GameStateDuel::~GameStateDuel() {
|
||||
End();
|
||||
}
|
||||
|
||||
void GameStateDuel::Start()
|
||||
{
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->ResetPrivateVRAM();
|
||||
renderer->EnableVSync(true);
|
||||
|
||||
|
||||
#ifdef TESTSUITE
|
||||
if (testSuite) delete testSuite;
|
||||
testSuite = NEW TestSuite("Res/test/_tests.txt");
|
||||
#endif
|
||||
|
||||
|
||||
mGamePhase = DUEL_CHOOSE_DECK1;
|
||||
|
||||
mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
mFont->SetBase(0); // using 2nd font
|
||||
|
||||
|
||||
menu = NEW SimpleMenu(11,this,mFont,SCREEN_WIDTH/2-100,20,200);
|
||||
menu->Add(12,"Back to main menu");
|
||||
menu->Add(13, "Cancel");
|
||||
|
||||
int decksneeded = 0;
|
||||
|
||||
|
||||
for (int i = 0; i<2; i ++){
|
||||
if (mParent->players[i] == PLAYER_TYPE_HUMAN){
|
||||
if (!deckmenu){
|
||||
decksneeded = 1;
|
||||
deckmenu = NEW SimpleMenu(1,this,mFont, 10 , 10, 100, "Choose a Deck");
|
||||
char buffer[100];
|
||||
for (int j=1; j<6; j++){
|
||||
sprintf(buffer, "Res/player/deck%i.txt",j);
|
||||
std::ifstream file(buffer);
|
||||
if(file){
|
||||
deckmenu->Add(j, GameState::menuTexts[j]);
|
||||
file.close();
|
||||
decksneeded = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decksneeded)
|
||||
mGamePhase = ERROR_NO_DECK;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateDuel::loadPlayer(int playerId, int decknb){
|
||||
if (decknb){ //Human Player
|
||||
char deckFile[255];
|
||||
sprintf(deckFile, "Res/player/deck%i.txt",decknb);
|
||||
char deckFileSmall[255];
|
||||
sprintf(deckFileSmall, "player_deck%i",decknb);
|
||||
int deck_cards_ids[100];
|
||||
int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
|
||||
deck[playerId] = NEW MTGPlayerCards(mParent->collection,deck_cards_ids, nb_elements);
|
||||
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
|
||||
}else{
|
||||
AIPlayerFactory playerCreator;
|
||||
mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,NULL);
|
||||
deck[playerId] = mPlayers[playerId]->game;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TESTSUITE
|
||||
void GameStateDuel::loadTestSuitePlayers(){
|
||||
OutputDebugString ("loading suite 1\n");
|
||||
if (!testSuite) return;
|
||||
for (int i = 0; i < 2; i++){
|
||||
if (mPlayers[i]){
|
||||
delete mPlayers[i];
|
||||
}
|
||||
mPlayers[i] = NEW TestSuiteAI(mParent->collection,testSuite, i);
|
||||
OutputDebugString ("loading suite 2\n");
|
||||
deck[i] = mPlayers[i]->game;
|
||||
}
|
||||
|
||||
if (game) delete game;
|
||||
game = NULL;
|
||||
if (!game){
|
||||
GameObserver::Init(mPlayers, 2);
|
||||
OutputDebugString ("loading suite 3\n");
|
||||
game = GameObserver::GetInstance();
|
||||
OutputDebugString ("loading suite 4\n");
|
||||
game->startGame(0,0);
|
||||
OutputDebugString ("loading suite 5\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GameStateDuel::End()
|
||||
{
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Ending GamestateDuel\n");
|
||||
#endif
|
||||
GameObserver::EndInstance();
|
||||
game = NULL;
|
||||
SAFE_DELETE(deckmenu);
|
||||
JRenderer::GetInstance()->EnableVSync(false);
|
||||
for (int i = 0; i < 2; i++){
|
||||
SAFE_DELETE(mPlayers[i]);
|
||||
SAFE_DELETE(deck[i]);
|
||||
}
|
||||
SAFE_DELETE(menu);
|
||||
#ifdef TESTSUITE
|
||||
SAFE_DELETE(testSuite);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void GameStateDuel::Update(float dt)
|
||||
{
|
||||
if (mGamePhase == ERROR_NO_DECK){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)){
|
||||
mParent->SetNextState(GAME_STATE_DECK_VIEWER);
|
||||
}
|
||||
}else if (mGamePhase == DUEL_CHOOSE_DECK1){
|
||||
if (mParent->players[0] == PLAYER_TYPE_HUMAN){
|
||||
deckmenu->Update(dt);
|
||||
}
|
||||
#ifdef TESTSUITE
|
||||
else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){
|
||||
if (testSuite && testSuite->loadNext()){
|
||||
loadTestSuitePlayers();
|
||||
mGamePhase = DUEL_PLAY;
|
||||
testSuite->initGame();
|
||||
char buf[4096];
|
||||
sprintf(buf, "nb cards in player2's graveyard : %i\n",mPlayers[1]->game->graveyard->nb_cards);
|
||||
LOG(buf);
|
||||
}else{
|
||||
mGamePhase = DUEL_END;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else{
|
||||
loadPlayer(0);
|
||||
mGamePhase = DUEL_CHOOSE_DECK2;
|
||||
}
|
||||
}else if(mGamePhase == DUEL_CHOOSE_DECK2){
|
||||
if (mParent->players[1] == PLAYER_TYPE_HUMAN){
|
||||
deckmenu->Update(dt);
|
||||
}
|
||||
|
||||
else{
|
||||
loadPlayer(1);
|
||||
mGamePhase = DUEL_PLAY;
|
||||
}
|
||||
|
||||
}else if (mGamePhase == DUEL_PLAY){
|
||||
if (!game){
|
||||
GameObserver::Init(mPlayers, 2);
|
||||
game = GameObserver::GetInstance();
|
||||
game->startGame();
|
||||
}
|
||||
game->Update(dt);
|
||||
if (game->gameOver){
|
||||
if (!mPlayers[0]->isAI() && mPlayers[1]->isAI() && mPlayers[0]!= game->gameOver){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "%p - %p", mPlayers[0], game->gameOver);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
PlayerData * playerdata = NEW PlayerData(mParent->collection);
|
||||
playerdata->credits+= 500;
|
||||
playerdata->save();
|
||||
delete playerdata;
|
||||
}
|
||||
mGamePhase = DUEL_END;
|
||||
#ifdef TESTSUITE
|
||||
if (mParent->players[1] == PLAYER_TYPE_TESTSUITE){
|
||||
if (testSuite->loadNext()){
|
||||
loadTestSuitePlayers();
|
||||
mGamePhase = DUEL_PLAY;
|
||||
testSuite->initGame();
|
||||
}else{
|
||||
mGamePhase = DUEL_END;
|
||||
}
|
||||
}else if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU){
|
||||
End();
|
||||
Start();
|
||||
}
|
||||
#endif
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_START)){
|
||||
mGamePhase = DUEL_MENU;
|
||||
}
|
||||
}else if (mGamePhase == DUEL_MENU){
|
||||
menu->Update(dt);
|
||||
}else{
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)){
|
||||
mParent->SetNextState(GAME_STATE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateDuel::Render()
|
||||
{
|
||||
//Erase
|
||||
JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0));
|
||||
|
||||
|
||||
if (game)
|
||||
game->Render();
|
||||
if (mGamePhase == DUEL_END){
|
||||
JRenderer::GetInstance()->ClearScreen(ARGB(200,0,0,0));
|
||||
char buffer[50];
|
||||
int p0life = mPlayers[0]->life;
|
||||
if (!mPlayers[0]->isAI() && mPlayers[1]->isAI() ){
|
||||
if (game->gameOver !=mPlayers[0]){
|
||||
sprintf (buffer, "Victory! Congratulations, You earn 500 credits");
|
||||
}else{
|
||||
sprintf (buffer, "You have been defeated");
|
||||
}
|
||||
}else{
|
||||
int winner = 2;
|
||||
if (game->gameOver !=mPlayers[0]){
|
||||
winner = 1;
|
||||
}
|
||||
sprintf(buffer, "Player %i wins (%i)", winner, p0life );
|
||||
}
|
||||
mFont->DrawString(buffer, 10, 150);
|
||||
}else if (mGamePhase == DUEL_CHOOSE_DECK1 || mGamePhase == DUEL_CHOOSE_DECK2){
|
||||
if (deckmenu)
|
||||
deckmenu->Render();
|
||||
}else if (mGamePhase == ERROR_NO_DECK){
|
||||
mFont->DrawString("NO DECK AVAILABLE,",0,SCREEN_HEIGHT/2);
|
||||
mFont->DrawString("PRESS CIRCLE TO GO TO THE DECK EDITOR!",0,SCREEN_HEIGHT/2 + 20);
|
||||
}else if (mGamePhase == DUEL_MENU){
|
||||
menu->Render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameStateDuel::ButtonPressed(int controllerId, int controlId)
|
||||
{
|
||||
switch (controlId)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
{
|
||||
if (mGamePhase == DUEL_CHOOSE_DECK1){
|
||||
loadPlayer(0,controlId);
|
||||
mGamePhase = DUEL_CHOOSE_DECK2;
|
||||
}else{
|
||||
loadPlayer(1,controlId);
|
||||
mGamePhase = DUEL_PLAY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
mParent->SetNextState(GAME_STATE_MENU);
|
||||
break;
|
||||
case 13:
|
||||
mGamePhase = DUEL_PLAY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GameStateOptions.h"
|
||||
#include "../include/GameApp.h"
|
||||
#include "../include/OptionItem.h"
|
||||
#include "../include/SimpleMenu.h"
|
||||
#include "../include/GameOptions.h"
|
||||
|
||||
GameStateOptions::GameStateOptions(GameApp* parent): GameState(parent) {
|
||||
optionsList = NULL;
|
||||
optionsMenu = NULL;
|
||||
}
|
||||
|
||||
|
||||
GameStateOptions::~GameStateOptions() {
|
||||
|
||||
}
|
||||
|
||||
void GameStateOptions::Start()
|
||||
{
|
||||
mState = SHOW_OPTIONS;
|
||||
JRenderer::GetInstance()->ResetPrivateVRAM();
|
||||
JRenderer::GetInstance()->EnableVSync(true);
|
||||
|
||||
optionsList = NEW OptionsList();
|
||||
if (GameApp::HasMusic) optionsList->Add(NEW OptionItem(OPTIONS_MUSICVOLUME, "Music volume", 100, 10));
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
optionsMenu = NEW SimpleMenu(102, this,mFont, 50,170,SCREEN_WIDTH-120);
|
||||
optionsMenu->Add(1, "Save & Back to Main Menu");
|
||||
optionsMenu->Add(2, "Back to Main Menu");
|
||||
optionsMenu->Add(3, "Cancel");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateOptions::End()
|
||||
{
|
||||
JRenderer::GetInstance()->EnableVSync(false);
|
||||
SAFE_DELETE(optionsList);
|
||||
}
|
||||
|
||||
|
||||
void GameStateOptions::Update(float dt)
|
||||
{
|
||||
if (mState == SHOW_OPTIONS){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_START)){
|
||||
mState = SHOW_OPTIONS_MENU;
|
||||
}
|
||||
|
||||
optionsList->Update(dt);
|
||||
}else{
|
||||
optionsMenu->Update(dt);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateOptions::Render()
|
||||
{
|
||||
//Erase
|
||||
JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0));
|
||||
optionsList->Render();
|
||||
|
||||
const char * const CreditsText[] = {
|
||||
"Wagic, The Homebrew ?! by WilLoW",
|
||||
"This is a work in progress and it contains bugs, deal with it",
|
||||
"updates on http://www.wololo.net/wagic",
|
||||
"",
|
||||
"Developped with the JGE++ Library",
|
||||
"http://jge.khors.com",
|
||||
"",
|
||||
"this freeware app is not endorsed by Wizards of the Coast, Inc",
|
||||
|
||||
};
|
||||
|
||||
const char * const MusicText[] = {
|
||||
"",
|
||||
"Music by Celestial Aeon Project, under Creative Commons License",
|
||||
"Their music can be downloaded at http://www.jamendo.com"
|
||||
};
|
||||
|
||||
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
mFont->SetColor(ARGB(255,200,200,200));
|
||||
mFont->SetScale(0.80);
|
||||
for (int i = 0; i < 8; i++){
|
||||
mFont->DrawString(CreditsText[i],SCREEN_WIDTH/2, 40 +18*i,JGETEXT_CENTER);
|
||||
}
|
||||
|
||||
if (GameApp::HasMusic){
|
||||
for (int i = 0; i < 3; i++){
|
||||
mFont->DrawString(MusicText[i],SCREEN_WIDTH/2, 40 +18*(8+i),JGETEXT_CENTER);
|
||||
}
|
||||
}
|
||||
mFont->SetScale(1.f);
|
||||
|
||||
if (mState == SHOW_OPTIONS_MENU){
|
||||
optionsMenu->Render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateOptions::ButtonPressed(int controllerId, int controlId)
|
||||
{
|
||||
switch (controlId){
|
||||
case 1:
|
||||
optionsList->save();
|
||||
case 2:
|
||||
mParent->SetNextState(GAME_STATE_MENU);
|
||||
break;
|
||||
case 3:
|
||||
mState = SHOW_OPTIONS;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
The shop is where the player can buy cards, decks...
|
||||
*/
|
||||
#include "../include/debug.h"
|
||||
#include <JRenderer.h>
|
||||
#include "../include/GameStateShop.h"
|
||||
#include "../include/GameApp.h"
|
||||
#include "../include/MTGDeck.h"
|
||||
|
||||
|
||||
GameStateShop::GameStateShop(GameApp* parent): GameState(parent) {}
|
||||
|
||||
|
||||
GameStateShop::~GameStateShop() {
|
||||
//End(); TODO FIX THAT
|
||||
}
|
||||
|
||||
void GameStateShop::Create(){
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GameStateShop::Start()
|
||||
{
|
||||
menu = NULL;
|
||||
mFont = GameApp::CommonRes->GetJLBFont("graphics/magic");
|
||||
mStage = STAGE_SHOP_SHOP;
|
||||
bgTexture = JRenderer::GetInstance()->LoadTexture("graphics/shop.jpg", TEX_TYPE_USE_VRAM);
|
||||
mBg = NEW JQuad(bgTexture, 0, 0, 400, 280); // Create background quad for rendering.
|
||||
backTexture = JRenderer::GetInstance()->LoadTexture("sets/back.jpg", TEX_TYPE_USE_VRAM);
|
||||
mBack = NEW JQuad(backTexture, 0, 0, 200, 285); // Create background quad for rendering.
|
||||
JRenderer::GetInstance()->ResetPrivateVRAM();
|
||||
JRenderer::GetInstance()->EnableVSync(true);
|
||||
|
||||
int sets[500];
|
||||
int nbsets = 0;
|
||||
for (int i = 0; i < MtgSets::SetsList->nb_items; i++){
|
||||
if (mParent->collection->countBySet(i) > 100){ //Only sets with more than 100 cards can get boosters and starters
|
||||
sets[nbsets] = i;
|
||||
nbsets++;
|
||||
}
|
||||
}
|
||||
if (nbsets){
|
||||
setId = sets[(rand() % nbsets)];
|
||||
}else{
|
||||
setId = (rand() % MtgSets::SetsList->nb_items);
|
||||
}
|
||||
JQuad * mBackThumb = GameApp::CommonRes->GetQuad("back_thumb");
|
||||
shop = NEW ShopItems(10, this, mFont, 10, 10, mParent->collection, setId);
|
||||
sprintf(starterBuffer, "%s Starter (60 cards)",MtgSets::SetsList->values[setId].c_str());
|
||||
sprintf(boosterBuffer, "%s Booster (15 cards)",MtgSets::SetsList->values[setId].c_str());
|
||||
shop->Add(starterBuffer,mBack,mBackThumb, 6000);
|
||||
shop->Add(boosterBuffer,mBack,mBackThumb, 1900);
|
||||
for (int i = 0; i < 4; i++){
|
||||
shop->Add(mParent->collection->randomCardId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameStateShop::End()
|
||||
{
|
||||
JRenderer::GetInstance()->EnableVSync(false);
|
||||
if (shop)
|
||||
SAFE_DELETE(shop);
|
||||
SAFE_DELETE(mBack);
|
||||
if(bgTexture)
|
||||
SAFE_DELETE(bgTexture);
|
||||
if(mBg)
|
||||
SAFE_DELETE(mBg);
|
||||
if(menu)
|
||||
SAFE_DELETE(menu);
|
||||
|
||||
}
|
||||
|
||||
void GameStateShop::Destroy(){
|
||||
}
|
||||
|
||||
void GameStateShop::Update(float dt)
|
||||
{
|
||||
if (mStage == STAGE_SHOP_MENU){
|
||||
if (menu){
|
||||
menu->Update(dt);
|
||||
}else{
|
||||
menu = NEW SimpleMenu(11,this,mFont,SCREEN_WIDTH/2-100,20,200);
|
||||
menu->Add(12,"Save & Back to main menu");
|
||||
menu->Add(13, "Cancel");
|
||||
}
|
||||
}else{
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_START)){
|
||||
mStage = STAGE_SHOP_MENU;
|
||||
}
|
||||
if (shop)
|
||||
shop->Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameStateShop::Render()
|
||||
{
|
||||
//Erase
|
||||
JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0));
|
||||
if (mBg)JRenderer::GetInstance()->RenderQuad(mBg,0,0);
|
||||
if (shop)
|
||||
shop->Render();
|
||||
if (mStage == STAGE_SHOP_MENU && menu){
|
||||
menu->Render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameStateShop::ButtonPressed(int controllerId, int controlId)
|
||||
{
|
||||
switch (controllerId){
|
||||
case 10:
|
||||
shop->pricedialog(controlId);
|
||||
break;
|
||||
case 11:
|
||||
if (controlId == 12){
|
||||
shop->saveAll();
|
||||
mParent->SetNextState(GAME_STATE_MENU);
|
||||
}else{
|
||||
mStage = STAGE_SHOP_SHOP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GroupOfCards.h"
|
||||
|
||||
|
||||
GroupOfCards::GroupOfCards(GameObserver * _game){
|
||||
game = _game;
|
||||
}
|
||||
|
||||
GroupOfCreatures::GroupOfCreatures(GameObserver * _game, int _filter, int _filterValue):GroupOfCards(_game){
|
||||
filter = _filter;
|
||||
filterValue = _filterValue;
|
||||
}
|
||||
|
||||
int GroupOfCreatures::includes(MTGCardInstance * card){
|
||||
if (!game->isACreature(card)){
|
||||
return 0;
|
||||
}
|
||||
switch (filter){
|
||||
case FILTER_SUBTYPE:
|
||||
return card->hasSubtype( filterValue);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GroupOfSpecificCards::GroupOfSpecificCards(GameObserver * _game, MTGCardInstance * _cards[], int _nb_cards):GroupOfCards(_game){
|
||||
int i;
|
||||
nb_cards = _nb_cards;
|
||||
for (i=0; i<nb_cards; i++){
|
||||
cards[i] = _cards[i];
|
||||
}
|
||||
}
|
||||
|
||||
GroupOfSpecificCards::GroupOfSpecificCards(GameObserver * _game, MTGCardInstance * card):GroupOfCards(_game){
|
||||
nb_cards = 1;
|
||||
cards[0] = card;
|
||||
}
|
||||
|
||||
int GroupOfSpecificCards::includes(MTGCardInstance * card){
|
||||
int i;
|
||||
for (i=0; i<nb_cards; i++){
|
||||
if (cards[i] == card){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GuiCardsController.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/GuiLayers.h"
|
||||
#include "../include/Player.h"
|
||||
|
||||
GuiLayer::GuiLayer(int id, GameObserver* _game):JGuiController(id, NULL){
|
||||
game = _game;
|
||||
modal = 0;
|
||||
hasFocus = 0;
|
||||
}
|
||||
|
||||
GuiLayer::~GuiLayer(){
|
||||
//TODO
|
||||
}
|
||||
|
||||
int GuiLayer::getMaxId(){
|
||||
return mCount;
|
||||
}
|
||||
|
||||
void GuiLayer::Update(float dt){
|
||||
for (int i=0;i<mCount;i++)
|
||||
if (mObjects[i]!=NULL)
|
||||
mObjects[i]->Update(dt);
|
||||
}
|
||||
|
||||
|
||||
void GuiLayer::resetObjects(){
|
||||
for (int i=0;i<mCount;i++)
|
||||
if (mObjects[i])
|
||||
delete mObjects[i];
|
||||
|
||||
mCount = 0;
|
||||
mCurr = 0;
|
||||
}
|
||||
|
||||
void GuiLayer::RenderMessageBackground(float x0, float y0, float width, int height){
|
||||
PIXEL_TYPE colors_up[] =
|
||||
{
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(128,255,255,255)
|
||||
};
|
||||
|
||||
PIXEL_TYPE colors_down[] =
|
||||
{
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(128,255,255,255),
|
||||
ARGB(0,255,255,255),
|
||||
ARGB(0,255,255,255)
|
||||
};
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(x0,y0,width,height/2,colors_up);
|
||||
renderer->FillRect(x0,y0+height/2,width,height/2,colors_down);
|
||||
|
||||
// mEngine->DrawLine(0,y0,SCREEN_WIDTH,y0,ARGB(128,255,255,255));
|
||||
// mEngine->DrawLine(0,y0+height,SCREEN_WIDTH,y0+height,ARGB(128,255,255,255));
|
||||
}
|
||||
|
||||
void GuiLayer::RenderMessageBackground(float y0, int height){
|
||||
RenderMessageBackground(0,y0,SCREEN_WIDTH, height);
|
||||
|
||||
}
|
||||
|
||||
int GuiLayer::isModal(){
|
||||
return modal;
|
||||
}
|
||||
|
||||
void GuiLayer::setModal(int _modal){
|
||||
modal=_modal;
|
||||
}
|
||||
|
||||
|
||||
int GuiLayer::getIndexOf(JGuiObject * object){
|
||||
for (int i=0; i<mCount; i++){
|
||||
if (mObjects[i] == object)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
JGuiObject * GuiLayer::getByIndex(int index){
|
||||
return mObjects[index];
|
||||
}
|
||||
|
||||
|
||||
GuiLayers::GuiLayers(){
|
||||
nbitems = 0;
|
||||
}
|
||||
|
||||
GuiLayers::~GuiLayers(){
|
||||
LOG("==Destroying GuiLayers==");
|
||||
for (int i=0; i<nbitems; i++){
|
||||
delete objects[i];
|
||||
}
|
||||
LOG("==Destroying GuiLayers Successful==");
|
||||
}
|
||||
int GuiLayers::unstopableRenderInProgress(){
|
||||
for (int i=0; i<nbitems; i++){
|
||||
if (objects[i]->unstopableRenderInProgress())
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GuiLayers::Add(GuiLayer * layer){
|
||||
if (nbitems >=MAX_GUI_LAYERS || nbitems < 0){
|
||||
LOG("OUT OF BOUND IN GuiLayers Add !!!");
|
||||
return;
|
||||
}
|
||||
objects[nbitems] = layer;
|
||||
nbitems++;
|
||||
}
|
||||
|
||||
void GuiLayers::Remove(){
|
||||
nbitems --;
|
||||
}
|
||||
|
||||
void GuiLayers::Update(float dt, Player * currentPlayer){
|
||||
int i;
|
||||
int modal = 0;
|
||||
int isAI = currentPlayer->isAI();
|
||||
for (i=0; i<nbitems; i++){
|
||||
objects[i]->hasFocus = 0;
|
||||
objects[i]->Update(dt);
|
||||
if (!isAI && !modal){
|
||||
objects[i]->hasFocus = 1;
|
||||
objects[i]->CheckUserInput(dt);
|
||||
modal = objects[i]->isModal();
|
||||
}
|
||||
}
|
||||
if (isAI){
|
||||
currentPlayer->Act();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiLayers::Render(){
|
||||
for (int i=nbitems-1; i>=0; i--){
|
||||
objects[i]->Render();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "GuiMessageBox.h"
|
||||
|
||||
|
||||
void GuiMessageBox::CheckUserInput(){
|
||||
if (mEngine->GetButtonClick(mActionButton))
|
||||
{
|
||||
if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed())
|
||||
{
|
||||
if (mListener != NULL)
|
||||
{
|
||||
mListener->ButtonPressed(mId, mObjects[mCurr]->GetId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mEngine->GetButtonState(PSP_CTRL_LEFT) || mEngine->GetButtonState(PSP_CTRL_UP) || mEngine->GetAnalogY()<64)
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_UP, dt))
|
||||
{
|
||||
int n = mCurr;
|
||||
n--;
|
||||
if (n<0)
|
||||
{
|
||||
if ((mStyle&JGUI_STYLE_WRAPPING))
|
||||
n = mCount-1;
|
||||
else
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonState(PSP_CTRL_RIGHT) || mEngine->GetButtonState(PSP_CTRL_DOWN) || mEngine->GetAnalogY()>192)
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_DOWN, dt))
|
||||
{
|
||||
int n = mCurr;
|
||||
n++;
|
||||
if (n>mCount-1)
|
||||
{
|
||||
if ((mStyle&JGUI_STYLE_WRAPPING))
|
||||
n = 0;
|
||||
else
|
||||
n = mCount-1;
|
||||
}
|
||||
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
mLastKey = 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Logger.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void Logger::Log(char * text){
|
||||
ofstream file (LOG_FILE,ios_base::app);
|
||||
if (file){
|
||||
file << text;
|
||||
file << "\n";
|
||||
file.close();
|
||||
}
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString(text);
|
||||
OutputDebugString("\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,310 @@
|
||||
//------------------------------------------------------
|
||||
//MTGCard Class
|
||||
//-------------------------------------------------
|
||||
//TODO Fill BasicAbilities
|
||||
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGCard.h"
|
||||
|
||||
#include "../include/TexturesCache.h"
|
||||
#include "../include/Subtypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
using std::string;
|
||||
|
||||
|
||||
const char * const MTGCard::Colors_To_Text[] = {"Artifact", "Green", "Blue", "Red", "Black", "White", "Land"};
|
||||
|
||||
MTGCard::MTGCard(){
|
||||
init();
|
||||
mCache = NULL;
|
||||
}
|
||||
|
||||
MTGCard::MTGCard(TexturesCache * cache, int set_id){
|
||||
init();
|
||||
mCache = cache;
|
||||
setId = set_id;
|
||||
}
|
||||
|
||||
const char * MTGCard::getSetName(){
|
||||
return MtgSets::SetsList->values[setId].c_str();
|
||||
}
|
||||
|
||||
MTGCard::MTGCard(MTGCard * source){
|
||||
mCache = source->mCache;
|
||||
for (int i = 0; i< NB_BASIC_ABILITIES; i++){
|
||||
basicAbilities[i] = source->basicAbilities[i];
|
||||
}
|
||||
for (int i = 0; i< MAX_TYPES_PER_CARD; i++){
|
||||
types[i] = source->types[i];
|
||||
}
|
||||
nb_types = source->nb_types;
|
||||
for (int i = 0; i< MTG_NB_COLORS; i++){
|
||||
colors[i] = source->colors[i];
|
||||
}
|
||||
manaCost.copy(source->getManaCost());
|
||||
|
||||
text = source->text;
|
||||
name = source->name;
|
||||
strcpy(image_name, source->image_name);
|
||||
|
||||
rarity = source->rarity;
|
||||
power = source->power;
|
||||
toughness = source->toughness;
|
||||
mtgid = source->mtgid;
|
||||
setId = source->setId;
|
||||
formattedTextInit = 0;
|
||||
magicText = source->magicText;
|
||||
spellTargetType = source->spellTargetType;
|
||||
alias = source->alias;
|
||||
}
|
||||
|
||||
int MTGCard::init(){
|
||||
nb_types = 0;
|
||||
for (int i = 0; i< NB_BASIC_ABILITIES; i++){
|
||||
basicAbilities[i] = 0;
|
||||
}
|
||||
for (int i = 0; i< MAX_TYPES_PER_CARD; i++){
|
||||
types[i] = 0;
|
||||
}
|
||||
for (int i = 0; i< MTG_NB_COLORS; i++){
|
||||
colors[i] = 0;
|
||||
}
|
||||
setId = 0;
|
||||
formattedTextInit = 0;
|
||||
magicText = "";
|
||||
spellTargetType = "";
|
||||
alias = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
JQuad * MTGCard::getQuad(int type){
|
||||
if (mCache == NULL){
|
||||
return NULL;
|
||||
}
|
||||
return mCache->getQuad(this, type);
|
||||
}
|
||||
|
||||
|
||||
JQuad * MTGCard::getThumb(){
|
||||
return getQuad(CACHE_THUMB);
|
||||
}
|
||||
|
||||
JQuad * MTGCard::getQuad(TexturesCache * cache){
|
||||
|
||||
return cache->getQuad(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MTGCard::isACreature(){
|
||||
return (hasSubtype("creature"));
|
||||
}
|
||||
|
||||
void MTGCard::setColor(int _color, int removeAllOthers){
|
||||
if (removeAllOthers){
|
||||
for (int i=0; i<MTG_NB_COLORS; i++){
|
||||
colors[i] = 0;
|
||||
}
|
||||
}
|
||||
colors[_color] = 1;
|
||||
}
|
||||
|
||||
int MTGCard::getColor(){
|
||||
int i = 0;
|
||||
for (int i=0; i<MTG_NB_COLORS; i++){
|
||||
if (colors[i]){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MTGCard::hasColor(int color){
|
||||
return (colors[color]);
|
||||
}
|
||||
|
||||
void MTGCard::setManaCost(string s){
|
||||
ManaCost::parseManaCost(s, &manaCost);
|
||||
for (int i = MTG_COLOR_GREEN; i <=MTG_COLOR_WHITE; i++){
|
||||
if (manaCost.hasColor(i)){
|
||||
setColor(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char * MTGCard::colorToString(){
|
||||
int color = getColor();
|
||||
if (color>=0 && color <=5){
|
||||
return Colors_To_Text[color];
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
void MTGCard::setMTGId(int id){
|
||||
mtgid = id;
|
||||
sprintf(image_name, "%d.jpg", mtgid);
|
||||
}
|
||||
|
||||
int MTGCard::getMTGId(){
|
||||
return mtgid;
|
||||
}
|
||||
int MTGCard::getId(){
|
||||
return mtgid;
|
||||
}
|
||||
|
||||
char MTGCard::getRarity(){
|
||||
return rarity;
|
||||
}
|
||||
|
||||
void MTGCard::setRarity(char _rarity){
|
||||
rarity = _rarity;
|
||||
}
|
||||
|
||||
void MTGCard::setType(const char * _type_text){
|
||||
setSubtype(_type_text);
|
||||
}
|
||||
|
||||
void MTGCard::addType(char * _type_text){
|
||||
setSubtype(_type_text);
|
||||
}
|
||||
|
||||
void MTGCard::setSubtype( string value){
|
||||
string s = value;
|
||||
while (s.size()){
|
||||
unsigned int found = s.find(" ");
|
||||
if (found != string::npos){
|
||||
int id = Subtypes::subtypesList->Add(s.substr(0,found));
|
||||
addType(id);
|
||||
s = s.substr(found+1);
|
||||
}else{
|
||||
int id = Subtypes::subtypesList->Add(s);
|
||||
addType(id);
|
||||
s = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MTGCard::addType(int id){
|
||||
types[nb_types] = id;
|
||||
nb_types++;
|
||||
}
|
||||
|
||||
|
||||
//Removes a type from the types of a given card
|
||||
//If removeAll is true, removes all occurences of this type, otherwise only removes the first occurence
|
||||
int MTGCard::removeType(string value, int removeAll){
|
||||
|
||||
int id = Subtypes::subtypesList->Add(value);
|
||||
return removeType(id, removeAll);
|
||||
}
|
||||
|
||||
int MTGCard::removeType(int id, int removeAll){
|
||||
int result = 0;
|
||||
for (int i = nb_types -1 ; i >=0; i--){
|
||||
if (types[i] == id){
|
||||
types[i] = types[nb_types -1];
|
||||
nb_types--;
|
||||
result++;
|
||||
if (!removeAll) return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char * MTGCard::getImageName(){
|
||||
return image_name;
|
||||
}
|
||||
|
||||
|
||||
void MTGCard::setText( string value){
|
||||
text = value;
|
||||
}
|
||||
|
||||
const char * MTGCard::getText(){
|
||||
return text.c_str();
|
||||
}
|
||||
|
||||
void MTGCard::addMagicText(string value){
|
||||
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
||||
if (magicText.size()) magicText.append("\n");
|
||||
magicText.append(value);
|
||||
}
|
||||
|
||||
void MTGCard::setName( string value){
|
||||
name = value;
|
||||
}
|
||||
|
||||
const char * MTGCard::getName(){
|
||||
return name.c_str();
|
||||
}
|
||||
|
||||
|
||||
ManaCost * MTGCard::getManaCost(){
|
||||
return &manaCost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MTGCard::hasType(int _type){
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i<nb_types; i++){
|
||||
if(types[i] == _type){
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGCard::hasSubtype(int _subtype){
|
||||
return(hasType(_subtype));
|
||||
}
|
||||
|
||||
int MTGCard::hasType(const char * _type){
|
||||
int id = Subtypes::subtypesList->Add(_type);
|
||||
return(hasType(id));
|
||||
}
|
||||
|
||||
|
||||
int MTGCard::hasSubtype(const char * _subtype){
|
||||
int id = Subtypes::subtypesList->Add(_subtype);
|
||||
return(hasType(id));
|
||||
}
|
||||
|
||||
int MTGCard::hasSubtype(string _subtype){
|
||||
int id = Subtypes::subtypesList->Add(_subtype);
|
||||
return(hasType(id));
|
||||
}
|
||||
|
||||
|
||||
int MTGCard::has(int basicAbility){
|
||||
return basicAbilities[basicAbility];
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
// Creature specific
|
||||
//---------------------------------------------
|
||||
void MTGCard::setPower(int _power){
|
||||
power = _power;
|
||||
}
|
||||
|
||||
int MTGCard::getPower(){
|
||||
return power;
|
||||
}
|
||||
|
||||
void MTGCard::setToughness(int _toughness){
|
||||
toughness = _toughness;
|
||||
}
|
||||
|
||||
int MTGCard::getToughness(){
|
||||
return toughness;
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
/*---------------------------------------------
|
||||
Card Instance
|
||||
Instance of a given MTGCard in the game
|
||||
Although there is only one MTGCard of each type, there can be as much Instances of it as needed in the game
|
||||
--------------------------------------------
|
||||
*/
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/CardDescriptor.h"
|
||||
#include "../include/Counters.h"
|
||||
|
||||
MTGCardInstance::MTGCardInstance(): MTGCard(), Damageable(0){
|
||||
LOG("==Creating MTGCardInstance==");
|
||||
initMTGCI();
|
||||
LOG("==Creating MTGCardInstance Successful==");
|
||||
}
|
||||
MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to): MTGCard(card), Damageable(card->getToughness()){
|
||||
LOG("==Creating MTGCardInstance==");
|
||||
initMTGCI();
|
||||
model = card;
|
||||
lifeOrig = life;
|
||||
belongs_to=_belongs_to;
|
||||
initAttackersDefensers();
|
||||
life=toughness;
|
||||
LOG("==Creating MTGCardInstance Successful==");
|
||||
|
||||
}
|
||||
|
||||
MTGCardInstance::~MTGCardInstance(){
|
||||
LOG("==Deleting MTGCardInstance==");
|
||||
SAFE_DELETE(blockers);
|
||||
SAFE_DELETE(counters);
|
||||
LOG("==Deleting MTGCardInstance Succesfull==");
|
||||
}
|
||||
void MTGCardInstance::initMTGCI(){
|
||||
model=NULL;
|
||||
lifeOrig = 0;
|
||||
doDamageTest = 0;
|
||||
belongs_to=NULL;
|
||||
tapped = 0;
|
||||
blockers = NEW Blockers();
|
||||
untapping = 0;
|
||||
summoningSickness = 0;
|
||||
target = NULL;
|
||||
nbprotections = 0;
|
||||
type_as_damageable = DAMAGEABLE_MTGCARDINSTANCE;
|
||||
banding = NULL;
|
||||
owner = NULL;
|
||||
changedZoneRecently = 0;
|
||||
counters = NEW Counters(this);
|
||||
}
|
||||
|
||||
|
||||
void MTGCardInstance::addType(int type){
|
||||
types[nb_types] = type;
|
||||
nb_types++;
|
||||
}
|
||||
|
||||
Blockers * MTGCardInstance::getBlockers(){
|
||||
return blockers;
|
||||
}
|
||||
|
||||
int MTGCardInstance::isInPlay(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
for (int i = 0 ; i < 2 ; i++){
|
||||
MTGGameZone * zone = game->players[i]->game->inPlay;
|
||||
if (zone->hasCard(this)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGCardInstance::afterDamage(){
|
||||
if (!doDamageTest) return 0;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096], *p = buf;
|
||||
sprintf(buf,"After Damage Test, life is %i for %s \n",life,model->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
doDamageTest = 0;
|
||||
if (life <=0 && isInPlay()){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
game->mLayers->stackLayer()->addPutInGraveyard(this);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MTGGameZone * MTGCardInstance::getCurrentZone(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
for (int i = 0; i < 2; i++){
|
||||
MTGPlayerCards * g = game->players[i]->game;
|
||||
MTGGameZone * zones[] = {g->inPlay,g->graveyard,g->hand, g->library};
|
||||
for (int k = 0; k < 4; k++){
|
||||
MTGGameZone * zone = zones[k];
|
||||
if (zone->hasCard(this)) return zone;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JQuad * MTGCardInstance::getIcon(){
|
||||
return getThumb();
|
||||
}
|
||||
|
||||
int MTGCardInstance::has(int basicAbility){
|
||||
return basicAbilities[basicAbility];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Taps the card
|
||||
void MTGCardInstance::tap(){
|
||||
tapped = 1;
|
||||
}
|
||||
|
||||
void MTGCardInstance::setUntapping(){
|
||||
untapping = 1;
|
||||
}
|
||||
|
||||
int MTGCardInstance::isUntapping(){
|
||||
return untapping;
|
||||
}
|
||||
|
||||
//Untaps the card
|
||||
void MTGCardInstance::untap(){
|
||||
if (untapping){
|
||||
tapped = 0;
|
||||
untapping = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Tells if the card is tapped or not
|
||||
int MTGCardInstance::isTapped(){
|
||||
return tapped;
|
||||
}
|
||||
|
||||
void MTGCardInstance::resetAllDamage(){
|
||||
//for (int i=0;i<nb_damages;i++){
|
||||
// delete damages[i];
|
||||
//}
|
||||
nb_damages = 0;
|
||||
}
|
||||
|
||||
void MTGCardInstance::regenerate(){
|
||||
tapped = 1;
|
||||
life = toughness;
|
||||
initAttackersDefensers();
|
||||
}
|
||||
|
||||
|
||||
int MTGCardInstance::initAttackersDefensers(){
|
||||
attacker = 0;
|
||||
defenser = NULL;
|
||||
banding = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Function to call to remove all damages, etc to a card (generally at the end of the turn)
|
||||
int MTGCardInstance::cleanup(){
|
||||
initAttackersDefensers();
|
||||
life=toughness;
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
if (!game || game->currentPlayer == controller()) summoningSickness = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Summoning Sickness
|
||||
* 212.3f A creature�fs activated ability with the tap symbol or the untap symbol in its activation cost
|
||||
* can�ft be played unless the creature has been under its controller�fs control since the start of his or
|
||||
* her most recent turn. A creature can�ft attack unless it has been under its controller�fs control
|
||||
* since the start of his or her most recent turn. This rule is informally called the �gsummoning
|
||||
* sickness�h rule. Ignore this rule for creatures with haste (see rule 502.5).
|
||||
*/
|
||||
int MTGCardInstance::hasSummoningSickness(){
|
||||
if (!summoningSickness) return 0;
|
||||
if (basicAbilities[HASTE]) return 0;
|
||||
if (!isACreature()) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MTGCardInstance::changeController(Player * newController){
|
||||
Player * originalOwner = controller();
|
||||
if (originalOwner == newController) return 0;
|
||||
originalOwner->game->inPlay->removeCard(this);
|
||||
newController->game->inPlay->addCard(this);
|
||||
summoningSickness = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Reset the card parameters
|
||||
int MTGCardInstance::reset(){
|
||||
cleanup();
|
||||
tapped=0;
|
||||
SAFE_DELETE(counters);
|
||||
counters = NEW Counters(this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Player * MTGCardInstance::controller(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
if (!game) return NULL;
|
||||
for (int i = 0; i < 2; i++){
|
||||
if (game->players[i]->game->inPlay->hasCard(this)) return game->players[i];
|
||||
if (game->players[i]->game->stack->hasCard(this)) return game->players[i];
|
||||
if (game->players[i]->game->graveyard->hasCard(this)) return game->players[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int MTGCardInstance::canAttack(){
|
||||
if (!hasSummoningSickness() && !tapped && isACreature() && basicAbilities[DEFENSER] !=1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MTGCardInstance::addToToughness(int value){
|
||||
toughness+=value;
|
||||
life+=value;
|
||||
doDamageTest = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MTGCardInstance::setToughness(int value){
|
||||
toughness=value;
|
||||
life=value;
|
||||
doDamageTest = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MTGCardInstance::canBlock(){
|
||||
if (!tapped && isACreature())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MTGCardInstance::canBlock(MTGCardInstance * opponent){
|
||||
if (!canBlock()) return 0;
|
||||
if (!opponent) return 1;
|
||||
if (!opponent->isAttacker()) return 0;
|
||||
|
||||
// Comprehensive rule 502.7f : If a creature with protection attacks, it can't be blocked by creatures that have the stated quality.
|
||||
if (opponent->protectedAgainst(this)) return 0;
|
||||
|
||||
if (opponent->basicAbilities[UNBLOCKABLE]) return 0;
|
||||
if (opponent->basicAbilities[FEAR] && !(hasColor(MTG_COLOR_ARTIFACT) || hasColor(MTG_COLOR_BLACK))) return 0;
|
||||
if (opponent->basicAbilities[FLYING] && !( basicAbilities[FLYING] || basicAbilities[REACH])) return 0;
|
||||
if (opponent->basicAbilities[SWAMPWALK] && controller()->game->inPlay->hasType("swamp")) return 0;
|
||||
if (opponent->basicAbilities[FORESTWALK] && controller()->game->inPlay->hasType("forest")) return 0;
|
||||
if (opponent->basicAbilities[ISLANDWALK] && controller()->game->inPlay->hasType("island")) return 0;
|
||||
if (opponent->basicAbilities[MOUNTAINWALK] && controller()->game->inPlay->hasType("mountain")) return 0;
|
||||
if (opponent->basicAbilities[PLAINSWALK] && controller()->game->inPlay->hasType("plains")) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
MTGCardInstance * MTGCardInstance::getNextPartner(){
|
||||
MTGInPlay * inplay = controller()->game->inPlay;
|
||||
MTGCardInstance * bandingPartner = inplay->getNextAttacker(banding);
|
||||
while (bandingPartner){
|
||||
if (basicAbilities[BANDING] || bandingPartner->basicAbilities[BANDING]) return bandingPartner;
|
||||
bandingPartner = inplay->getNextAttacker(bandingPartner);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MTGCardInstance::unband(){
|
||||
if (!banding) return;
|
||||
|
||||
MTGCardInstance * _banding = banding;
|
||||
banding = NULL;
|
||||
MTGCardInstance * newbanding = NULL;
|
||||
MTGInPlay * inplay = controller()->game->inPlay;
|
||||
int nbpartners = inplay->nbPartners(this);
|
||||
MTGCardInstance * card = inplay->getNextAttacker(NULL);
|
||||
while(card){
|
||||
if (card != this){
|
||||
if (card->banding == _banding){
|
||||
if (nbpartners == 1){
|
||||
card->banding = NULL;
|
||||
return;
|
||||
}else{
|
||||
if (!newbanding) newbanding = card;
|
||||
card->banding = newbanding;
|
||||
}
|
||||
}
|
||||
}
|
||||
card = inplay->getNextAttacker(card);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
int MTGCardInstance::toggleAttacker(){
|
||||
//TODO more controls ?
|
||||
if (canAttack()){
|
||||
if (!attacker){
|
||||
attacker = 1;
|
||||
tapped = 1;
|
||||
return 1;
|
||||
}else{
|
||||
MTGCardInstance * bandingPartner = getNextPartner();
|
||||
if (bandingPartner){
|
||||
if (banding) unband();
|
||||
if (!bandingPartner->banding) bandingPartner->banding = bandingPartner;
|
||||
banding = bandingPartner->banding;
|
||||
return 1;
|
||||
}else{
|
||||
attacker = 0;
|
||||
tapped = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGCardInstance::isAttacker(){
|
||||
return attacker;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGCardInstance::isDefenser(){
|
||||
return defenser;
|
||||
}
|
||||
|
||||
|
||||
int MTGCardInstance::nbOpponents(){
|
||||
int result= 0;
|
||||
MTGCardInstance* opponent = getNextOpponent();
|
||||
while (opponent){
|
||||
result++;
|
||||
opponent = getNextOpponent(opponent);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//Returns opponents to this card for this turn. This * should * take into account banding
|
||||
MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
int foundprevious = 0;
|
||||
if (!previous) foundprevious = 1;
|
||||
if (attacker && game->currentPlayer->game->inPlay->hasCard(this)){
|
||||
MTGInPlay * inPlay = game->opponent()->game->inPlay;
|
||||
for (int i = 0; i < inPlay->nb_cards; i ++){
|
||||
MTGCardInstance * current = inPlay->cards[i];
|
||||
if (current == previous){
|
||||
foundprevious = 1;
|
||||
}else if (foundprevious){
|
||||
MTGCardInstance * defensersOpponent = current->isDefenser();
|
||||
if (defensersOpponent && (defensersOpponent == this || (banding && defensersOpponent->banding == banding))){
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if (defenser && game->opponent()->game->inPlay->hasCard(this)){
|
||||
MTGInPlay * inPlay = game->currentPlayer->game->inPlay;
|
||||
for (int i = 0; i < inPlay->nb_cards; i ++){
|
||||
MTGCardInstance * current = inPlay->cards[i];
|
||||
if (current == previous){
|
||||
foundprevious = 1;
|
||||
}else if (foundprevious){
|
||||
if (defenser == current || (current->banding && defenser->banding == current->banding)){
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent){
|
||||
if (canBlock()){
|
||||
if (canBlock(opponent)){
|
||||
defenser = opponent;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MTGCardInstance::addProtection(CardDescriptor * cd){
|
||||
protections[nbprotections] = cd;
|
||||
nbprotections++;
|
||||
return nbprotections;
|
||||
}
|
||||
|
||||
int MTGCardInstance::removeProtection(CardDescriptor * cd, int erase){
|
||||
for (int i = 0; i < nbprotections ; i++){
|
||||
if (protections[i] == cd){
|
||||
if (erase) delete (protections[i]);
|
||||
protections[i] = protections[nbprotections -1];
|
||||
protections[nbprotections -1] = NULL;
|
||||
nbprotections--;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGCardInstance::protectedAgainst(MTGCardInstance * card){
|
||||
for (int i = 0; i < nbprotections ; i++){
|
||||
if (protections[i]->match(card)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGDeck.h"
|
||||
#include "../include/utils.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
#include <JGE.h>
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MtgSets * MtgSets::SetsList = NEW MtgSets();
|
||||
|
||||
|
||||
|
||||
MtgSets::MtgSets(){
|
||||
nb_items = 0;
|
||||
}
|
||||
|
||||
int MtgSets::Add(const char * name){
|
||||
string value = name;
|
||||
values[nb_items] = value;
|
||||
nb_items++;
|
||||
return nb_items - 1;
|
||||
}
|
||||
|
||||
|
||||
int MTGAllCards::processConfLine(char *buffer, MTGCard *card){
|
||||
string s = buffer;
|
||||
unsigned int i = s.find_first_of("=");
|
||||
if (i == string::npos) return 0;
|
||||
string key = s.substr(0,i);
|
||||
string value = s.substr(i+1);
|
||||
|
||||
if(key.compare( "auto")==0){
|
||||
card->addMagicText(value);
|
||||
}
|
||||
else if(key.compare( "alias")==0){
|
||||
card->alias=atoi(value.c_str());
|
||||
}
|
||||
else if(key.compare( "target")==0){
|
||||
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
||||
card->spellTargetType=value;
|
||||
}
|
||||
else if(key.compare( "text")==0){
|
||||
card->setText(value);
|
||||
}else if (key.compare("abilities")==0){
|
||||
//Specific Abilities
|
||||
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
||||
for (int j = 0; j < NB_BASIC_ABILITIES; j++){
|
||||
unsigned int found = value.find(MTGBasicAbilities[j]);
|
||||
if (found != string::npos){
|
||||
card->basicAbilities[j] = 1;
|
||||
}
|
||||
}
|
||||
}else if(key.compare("id")==0){
|
||||
card->setMTGId(atoi(value.c_str()));
|
||||
}else if(key.compare("name")==0){
|
||||
card->setName(value);
|
||||
}else if(key.compare("rarity")==0){
|
||||
card->setRarity (value.c_str()[0]);
|
||||
}else if(key.compare("mana")==0){
|
||||
std::transform( value.begin(), value.end(), value.begin(),::tolower );
|
||||
card->setManaCost(value);
|
||||
}else if(key.compare("type")==0){
|
||||
switch(value.c_str()[0]){
|
||||
case 'C':
|
||||
card->setType( "Creature");
|
||||
break;
|
||||
case 'A':
|
||||
card->setType( "Artifact");
|
||||
card->setColor(MTG_COLOR_ARTIFACT);
|
||||
if (value.c_str()[8] == ' ' && value.c_str()[9] == 'C')
|
||||
card->setSubtype("Creature");
|
||||
break;
|
||||
case 'E':
|
||||
card->setType( "Enchantment");
|
||||
break;
|
||||
case 'S':
|
||||
card->setType( "Sorcery");
|
||||
break;
|
||||
case 'B'://Basic Land
|
||||
card->setColor(MTG_COLOR_LAND);
|
||||
card->setType("Land");
|
||||
break;
|
||||
case 'L':
|
||||
card->setColor(MTG_COLOR_LAND);
|
||||
card->setType( "Land");
|
||||
break;
|
||||
case 'I':
|
||||
card->setType( "Instant");
|
||||
break;
|
||||
default:
|
||||
card->setType( "Error");
|
||||
break;
|
||||
|
||||
}
|
||||
}else if(key.compare("power")==0){
|
||||
card->setPower (atoi(value.c_str()));
|
||||
}else if(key.compare("subtype")==0){
|
||||
card->setSubtype(value);
|
||||
}else if(key.compare("toughness")==0){
|
||||
card->setToughness(atoi(value.c_str()));
|
||||
}else{
|
||||
}
|
||||
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
void MTGAllCards::initCounters(){
|
||||
for (int i=0; i< MTG_NB_COLORS; i++){
|
||||
colorsCount[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void MTGAllCards::init(){
|
||||
mCache = NULL;
|
||||
total_cards = 0;
|
||||
initCounters();
|
||||
srand(time(0)); // initialize random
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MTGAllCards::load(const char * config_file, const char * set_name,int autoload){
|
||||
conf_read_mode = 0;
|
||||
int file_size = filesize(config_file);
|
||||
conf_buffer = (char *) malloc(file_size);
|
||||
read_cursor = 0;
|
||||
// conf_fd = sceIoOpen(config_file, PSP_O_RDONLY, 0777);
|
||||
read_file(config_file, conf_buffer, file_size );
|
||||
int set_id = MtgSets::SetsList->Add(set_name);
|
||||
if (autoload){
|
||||
while(readConfLine(set_id)){};
|
||||
}
|
||||
return total_cards;
|
||||
}
|
||||
|
||||
MTGAllCards::MTGAllCards(){
|
||||
init();
|
||||
}
|
||||
|
||||
MTGAllCards::~MTGAllCards(){
|
||||
}
|
||||
|
||||
void MTGAllCards::destroyAllCards(){
|
||||
for (int i= 0; i < total_cards; i++){
|
||||
delete collection[i];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
MTGAllCards::MTGAllCards(const char * config_file, const char * set_name){
|
||||
MTGAllCards(config_file, set_name, NULL);
|
||||
}
|
||||
|
||||
MTGAllCards::MTGAllCards(TexturesCache * cache){
|
||||
init();
|
||||
mCache = cache;
|
||||
}
|
||||
|
||||
MTGAllCards::MTGAllCards(const char * config_file, const char * set_name, TexturesCache * cache){
|
||||
init();
|
||||
mCache = cache;
|
||||
load(config_file,set_name, 0);
|
||||
}
|
||||
|
||||
|
||||
MTGCard * MTGAllCards::_(int i){
|
||||
if (i < total_cards) return collection[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int MTGAllCards::randomCardId(){
|
||||
int id = (rand() % total_cards);
|
||||
return collection[id]->getMTGId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MTGAllCards::countBySet(int setId){
|
||||
int result = 0;
|
||||
for (int i=0; i< total_cards; i++){
|
||||
if(collection[i]->setId == setId){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//TODO more efficient way ?
|
||||
int MTGAllCards::countByType(const char * _type){
|
||||
int result = 0;
|
||||
for (int i=0; i< total_cards; i++){
|
||||
if(collection[i]->hasType(_type)){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int MTGAllCards::countByColor(int color){
|
||||
if (colorsCount[color] == 0){
|
||||
for (int i=0; i< MTG_NB_COLORS; i++){
|
||||
colorsCount[i] = 0;
|
||||
}
|
||||
for (int i=0; i< total_cards; i++){
|
||||
int j = collection[i]->getColor();
|
||||
|
||||
colorsCount[j]++;
|
||||
}
|
||||
}
|
||||
return colorsCount[color];
|
||||
}
|
||||
|
||||
int MTGAllCards::totalCards(){
|
||||
return (total_cards);
|
||||
}
|
||||
|
||||
int MTGAllCards::readConfLine(int set_id){
|
||||
char buffer[BUFSIZE];
|
||||
read_cursor = readline(conf_buffer, buffer, read_cursor);
|
||||
if (read_cursor){
|
||||
switch(conf_read_mode) {
|
||||
case 0:
|
||||
conf_read_mode = 1;
|
||||
collection[total_cards] = NEW MTGCard(mCache,set_id);
|
||||
break;
|
||||
case 1:
|
||||
if (buffer[0] == '[' && buffer[1] == '/'){
|
||||
conf_read_mode = 0;
|
||||
total_cards++;
|
||||
}else{
|
||||
processConfLine(buffer, collection[total_cards]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}else{
|
||||
free (conf_buffer);
|
||||
}
|
||||
|
||||
return read_cursor;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
MTGCard * MTGAllCards::getCardById(int id){
|
||||
int i;
|
||||
for (i=0; i<total_cards; i++){
|
||||
int cardId = collection[i]->getMTGId();
|
||||
if (cardId == id){
|
||||
return collection[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MTGDeck::MTGDeck(const char * config_file, TexturesCache * cache, MTGAllCards * _allcards){
|
||||
mCache = cache;
|
||||
total_cards = 0;
|
||||
allcards = _allcards;
|
||||
filename = config_file;
|
||||
std::ifstream file(config_file);
|
||||
std::string s;
|
||||
|
||||
if(file){
|
||||
while(std::getline(file,s)){
|
||||
int cardnb = atoi(s.c_str());
|
||||
if (cardnb) add(cardnb);
|
||||
}
|
||||
file.close();
|
||||
}else{
|
||||
//TODO Error management
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MTGDeck::addRandomCards(int howmany, int setId, int rarity, const char * _subtype){
|
||||
int collectionTotal = allcards->totalCards();
|
||||
if (!collectionTotal) return 0;
|
||||
if (setId == -1 && rarity == -1 && !_subtype){
|
||||
for (int i = 0; i < howmany; i++){
|
||||
int id = (rand() % collectionTotal);
|
||||
add(allcards->_(id));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
char subtype[4096];
|
||||
if (_subtype)
|
||||
sprintf(subtype, _subtype);
|
||||
|
||||
|
||||
int subcollection[TOTAL_NUMBER_OF_CARDS];
|
||||
int subtotal = 0;
|
||||
for (int i = 0; i < collectionTotal; i++){
|
||||
MTGCard * card = allcards->_(i);
|
||||
if ((setId == -1 || card->setId == setId) &&
|
||||
(rarity == -1 || card->getRarity()==rarity) &&
|
||||
(!_subtype || card->hasSubtype(subtype))
|
||||
){
|
||||
subcollection[subtotal] = i;
|
||||
subtotal++;
|
||||
}
|
||||
}
|
||||
if (subtotal == 0) return 0;
|
||||
for (int i = 0; i < howmany; i++){
|
||||
int id = (rand() % subtotal);
|
||||
add(allcards->_(subcollection[id]));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MTGDeck::add(int cardid){
|
||||
MTGCard * card = allcards->getCardById(cardid);
|
||||
add(card);
|
||||
return total_cards;
|
||||
}
|
||||
|
||||
int MTGDeck::add(MTGCard * card){
|
||||
if (!card) return 0;
|
||||
collection[total_cards] = card;
|
||||
++total_cards;
|
||||
initCounters();
|
||||
return total_cards;
|
||||
}
|
||||
|
||||
|
||||
int MTGDeck::removeAll(){
|
||||
total_cards = 0;
|
||||
initCounters();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MTGDeck::remove(int cardid){
|
||||
MTGCard * card = getCardById(cardid);
|
||||
return remove(card);
|
||||
}
|
||||
|
||||
int MTGDeck::remove(MTGCard * card){
|
||||
for (int i = 0; i<total_cards; i++){
|
||||
if (collection[i] == card){
|
||||
collection[i] = collection[total_cards - 1];
|
||||
total_cards--;
|
||||
initCounters();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGDeck::save(){
|
||||
std::ofstream file(filename.c_str());
|
||||
char writer[10];
|
||||
if (file){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("saving");
|
||||
#endif
|
||||
for (int i = 0; i<total_cards; i++){
|
||||
sprintf(writer,"%i\n", collection[i]->getMTGId());
|
||||
file<<writer;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGGamePhase.h"
|
||||
|
||||
|
||||
MTGGamePhase::MTGGamePhase(int id):ActionElement(id){
|
||||
animation = 0;
|
||||
currentState = -1;
|
||||
mFont= GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
mFont->SetBase(0); // using 2nd font
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MTGGamePhase::Render(){
|
||||
/*if (animation){
|
||||
RenderMessageBackground(10, 100);
|
||||
mFont->DrawString(MTGPhaseNames[currentState], SCREEN_WIDTH_F/2, 30, JGETEXT_CENTER);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void MTGGamePhase::Update(float dt){
|
||||
|
||||
int newState = GameObserver::GetInstance()->getCurrentGamePhase();
|
||||
if (newState != currentState){
|
||||
activeState = ACTIVE;
|
||||
animation = 1;
|
||||
currentState = newState;
|
||||
|
||||
switch (currentState){
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (animation > 0){
|
||||
fprintf(stderr, "animation = %f", animation);
|
||||
animation -= 0.05;
|
||||
}else{
|
||||
activeState = INACTIVE;
|
||||
animation = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MTGGamePhase::CheckUserInput(float dt){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
if (activeState == INACTIVE){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_RTRIGGER) && game->currentActionPlayer == game->currentlyActing())
|
||||
{
|
||||
activeState = ACTIVE;
|
||||
game->userRequestNextGamePhase();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGGameZones.h"
|
||||
#include "../include/Player.h"
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
//------------------------------
|
||||
//Players Game
|
||||
//------------------------------
|
||||
|
||||
MTGPlayerCards::MTGPlayerCards(MTGAllCards * _collection, int * idList, int idListSize){
|
||||
|
||||
init();
|
||||
int i;
|
||||
collection = _collection;
|
||||
for (i=0;i<idListSize;i++){
|
||||
MTGCard * card = collection->getCardById(idList[i]);
|
||||
if (card){
|
||||
MTGCardInstance * newCard = NEW MTGCardInstance(card, this);
|
||||
library->addCard(newCard);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
MTGPlayerCards::~MTGPlayerCards(){
|
||||
if(library) delete library;
|
||||
if(graveyard) delete graveyard;
|
||||
if(hand) delete hand;
|
||||
if(inPlay) delete inPlay;
|
||||
if(stack) delete stack;
|
||||
}
|
||||
|
||||
void MTGPlayerCards::setOwner(Player * player){
|
||||
library->setOwner(player);
|
||||
}
|
||||
|
||||
void MTGPlayerCards::initGame(int shuffle, int draw){
|
||||
if (shuffle) library->shuffle();
|
||||
if (draw){
|
||||
for (int i=0;i<7;i++){
|
||||
drawFromLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MTGPlayerCards::drawFromLibrary(){
|
||||
MTGCardInstance * drownCard = library->draw();
|
||||
hand->addCard(drownCard);
|
||||
}
|
||||
|
||||
void MTGPlayerCards::init(){
|
||||
library = NEW MTGLibrary();
|
||||
graveyard = NEW MTGGraveyard();
|
||||
hand = NEW MTGHand();
|
||||
inPlay = NEW MTGInPlay();
|
||||
stack = NEW MTGStack();
|
||||
}
|
||||
|
||||
|
||||
void MTGPlayerCards::showHand(){
|
||||
hand->debugPrint();
|
||||
}
|
||||
|
||||
|
||||
void MTGPlayerCards::putInPlay(MTGCardInstance * card){
|
||||
hand->removeCard(card);
|
||||
stack->removeCard(card); //Which one is it ???
|
||||
|
||||
inPlay->addCard(card);
|
||||
card->summoningSickness = 1;
|
||||
card->changedZoneRecently = 1.f;
|
||||
}
|
||||
|
||||
void MTGPlayerCards::putInGraveyard(MTGCardInstance * card){
|
||||
if (inPlay->hasCard(card)){
|
||||
putInZone(card,inPlay, graveyard);
|
||||
}else if (stack->hasCard(card)){
|
||||
putInZone(card,stack, graveyard);
|
||||
}else{
|
||||
putInZone(card,hand, graveyard);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGameZone * to){
|
||||
if (from->removeCard(card)){
|
||||
to->addCard(card);
|
||||
card->changedZoneRecently = 1.f;
|
||||
//if (to == graveyard){
|
||||
card->reset();
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
void MTGPlayerCards::discardRandom(MTGGameZone * from){
|
||||
if (!from->nb_cards)
|
||||
return;
|
||||
int r = rand() % (from->nb_cards);
|
||||
putInZone(from->cards[r],from, graveyard);
|
||||
}
|
||||
|
||||
int MTGPlayerCards::isInPlay(MTGCardInstance * card){
|
||||
if (inPlay->hasCard(card)){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
// Zones specific code
|
||||
//--------------------------------------
|
||||
|
||||
MTGGameZone::MTGGameZone(){
|
||||
nb_cards= 0;
|
||||
lastCardDrawn = NULL;
|
||||
}
|
||||
|
||||
MTGGameZone::~MTGGameZone(){
|
||||
for (int i=0; i<nb_cards; i++) {
|
||||
delete cards[i];
|
||||
}
|
||||
}
|
||||
|
||||
void MTGGameZone::setOwner(Player * player){
|
||||
for (int i=0; i<nb_cards; i++) {
|
||||
cards[i]->owner = player;
|
||||
}
|
||||
owner = player;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card){
|
||||
int i;
|
||||
for (i=0; i<(nb_cards); i++) {
|
||||
if (cards[i] == card){
|
||||
cards[i] = cards[nb_cards -1];
|
||||
nb_cards--;
|
||||
return card;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card){
|
||||
for (int i=0; i<(nb_cards); i++) {
|
||||
if (cards[i] == card){
|
||||
return cards[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int MTGGameZone::countByType(const char * value){
|
||||
int result = 0 ;
|
||||
for (int i=0; i<(nb_cards); i++) {
|
||||
if (cards[i]->hasType(value)){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int MTGGameZone::hasType(const char * value){
|
||||
for (int i=0; i<(nb_cards); i++) {
|
||||
if (cards[i]->hasType(value)){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void MTGGameZone::cleanupPhase(){
|
||||
for (int i=0; i<(nb_cards); i++)
|
||||
(cards[i])->cleanup();
|
||||
}
|
||||
|
||||
void MTGGameZone::shuffle(){
|
||||
int i;
|
||||
for (i=0; i<(nb_cards); i++) {
|
||||
int r = i + (rand() % (nb_cards-i)); // Random remaining position.
|
||||
MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp;
|
||||
}
|
||||
srand(time(0)); // initialize seed "randomly" TODO :improve
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MTGGameZone::addCard(MTGCardInstance * card){
|
||||
if (!card) return;
|
||||
cards[nb_cards] = card;
|
||||
nb_cards++;
|
||||
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGGameZone::draw(){
|
||||
if (!nb_cards) return NULL;
|
||||
nb_cards--;
|
||||
lastCardDrawn = cards[nb_cards];
|
||||
return cards[nb_cards];
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGLibrary::draw(){
|
||||
if (!nb_cards) {
|
||||
GameObserver::GetInstance()->gameOver = this->owner;
|
||||
}
|
||||
return MTGGameZone::draw();
|
||||
}
|
||||
|
||||
void MTGGameZone::debugPrint(){
|
||||
int i;
|
||||
for (i=0;i<nb_cards;i++){
|
||||
MTGCard * card = cards[i]->model;
|
||||
fprintf(stderr, "%s", card->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------
|
||||
int MTGInPlay::nbDefensers( MTGCardInstance * attacker){
|
||||
int result = 0;
|
||||
MTGCardInstance * defenser = getNextDefenser(NULL, attacker);
|
||||
while (defenser){
|
||||
result++;
|
||||
defenser = getNextDefenser(defenser, attacker);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//Return the number of creatures this card is banded with
|
||||
//Number of creatures in the band is n+1 !!!
|
||||
int MTGInPlay::nbPartners(MTGCardInstance * attacker){
|
||||
int result = 0;
|
||||
if (!attacker->banding) return 0;
|
||||
for (int i = 0; i < nb_cards; i ++){
|
||||
if (cards[i]->banding == attacker->banding) result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGInPlay::getNextDefenser(MTGCardInstance * previous, MTGCardInstance * attacker){
|
||||
int foundprevious = 0;
|
||||
if (previous == NULL){
|
||||
foundprevious = 1;
|
||||
}
|
||||
for (int i = 0; i < nb_cards; i ++){
|
||||
MTGCardInstance * current = cards[i];
|
||||
if (current == previous){
|
||||
foundprevious = 1;
|
||||
}else if (foundprevious && current->isDefenser() == attacker){
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MTGCardInstance * MTGInPlay::getNextAttacker(MTGCardInstance * previous){
|
||||
int foundprevious = 0;
|
||||
if (previous == NULL){
|
||||
foundprevious = 1;
|
||||
}
|
||||
for (int i = 0; i < nb_cards; i ++){
|
||||
MTGCardInstance * current = cards[i];
|
||||
if (current == previous){
|
||||
foundprevious = 1;
|
||||
}else if (foundprevious && current->isAttacker()){
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MTGInPlay::untapAll(){
|
||||
int i;
|
||||
for (i = 0; i < nb_cards; i ++){
|
||||
cards[i]->setUntapping();
|
||||
if (cards[i]->getBlockers()->isEmpty()){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Can untap %s\n", cards[i]->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
cards[i]->untap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------
|
||||
void MTGLibrary::shuffleTopToBottom(int nbcards){
|
||||
if (nbcards>nb_cards) nbcards = nb_cards;
|
||||
MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS];
|
||||
for (int i= nb_cards-nbcards; i<(nb_cards); i++) {
|
||||
int r = i + (rand() % (nbcards-i)); // Random remaining position.
|
||||
MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp;
|
||||
}
|
||||
for (int i= 0; i < nbcards; i++){
|
||||
_cards[i] = cards[nb_cards - 1 - i];
|
||||
}
|
||||
for (int i = nbcards; i < nb_cards; i++){
|
||||
_cards[i] = cards[i - nb_cards];
|
||||
}
|
||||
for (int i=0 ; i < nb_cards; i++){
|
||||
cards[i] = _cards[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGGuiHand.h"
|
||||
#include "../include/CardGui.h"
|
||||
|
||||
MTGGuiHand::MTGGuiHand(int id, GameObserver * _game):GuiCardsController(id, _game){
|
||||
mShowHand = HAND_HIDE;
|
||||
mAnimState = 0;
|
||||
currentPlayer = NULL;
|
||||
mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
for (int i = 0; i < 2; i++){
|
||||
currentId[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiHand::updateCards(){
|
||||
Player * player = GameObserver::GetInstance()->currentlyActing();
|
||||
if (player->isAI()) player = GameObserver::GetInstance()->players[0];
|
||||
int nb_cards = player->game->hand->nb_cards;
|
||||
if (mCount != nb_cards || player != currentPlayer ){ //if the number of cards has changed, then an update occured (is this test engouh ?)
|
||||
resetObjects();
|
||||
if (currentId[player->getId()] >= nb_cards) currentId[player->getId()] = nb_cards - 1;
|
||||
for (int i = 0;i<nb_cards; i++){
|
||||
CardGui * object = NEW CardGui(i, player->game->hand->cards[i],(float)40, (float)450 - (nb_cards-i) *35, SCREEN_HEIGHT_F - mAnimState*60, i == currentId[player->getId()]);
|
||||
Add(object);
|
||||
if ( i == currentId[player->getId()]) mCurr = i;
|
||||
}
|
||||
currentPlayer = player;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiHand::Update(float dt){
|
||||
updateCards();
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
((CardGui *)mObjects[i])->y= SCREEN_HEIGHT - mAnimState*60;
|
||||
}
|
||||
}
|
||||
|
||||
GuiCardsController::Update(dt);
|
||||
currentId[game->currentlyActing()->getId()] = mCurr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MTGGuiHand::CheckUserInput(float dt){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_LTRIGGER)) {
|
||||
if (mShowHand == HAND_HIDE){
|
||||
mShowHand = HAND_SHOW_ANIMATION;
|
||||
}
|
||||
if (mShowHand == HAND_SHOW){
|
||||
mShowHand = HAND_HIDE_ANIMATION;
|
||||
}
|
||||
}else if (mEngine->GetButtonState(PSP_CTRL_LEFT)){
|
||||
//mGamePhase = NO_USER_INPUT;
|
||||
}
|
||||
|
||||
if (mShowHand == HAND_SHOW_ANIMATION){
|
||||
mAnimState +=7 *dt;
|
||||
if (mAnimState > 1){
|
||||
mAnimState = 1;
|
||||
mShowHand = HAND_SHOW;
|
||||
}
|
||||
}else if(mShowHand == HAND_HIDE_ANIMATION){
|
||||
mAnimState -=7 *dt;
|
||||
if (mAnimState < 0){
|
||||
mAnimState = 0;
|
||||
mShowHand = HAND_HIDE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mShowHand == HAND_HIDE || currentPlayer->isAI()){
|
||||
modal = 0;
|
||||
}else{
|
||||
modal = 1;
|
||||
GuiCardsController::CheckUserInput(dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MTGGuiHand::Render(){
|
||||
if (mShowHand != HAND_HIDE){
|
||||
// if (currentPlayer && !currentPlayer->isAI()){
|
||||
RenderMessageBackground(440-mCount * 35 , SCREEN_HEIGHT - mAnimState*60 - 10, mCount * 35 + 20, 70);
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL && i!=mCurr){
|
||||
mObjects[i]->Render();
|
||||
}
|
||||
}
|
||||
if (mCount && mObjects[mCurr] != NULL){
|
||||
mObjects[mCurr]->Render();
|
||||
if (showBigCards) ((CardGui *)mObjects[mCurr])->RenderBig(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
/* This class handles the display on the main game screen :
|
||||
cards in play, graveyard, library, games phases, Players avatars
|
||||
*/
|
||||
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGGuiPlay.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/CardGui.h"
|
||||
#include "../include/CardDisplay.h"
|
||||
|
||||
#define ZX_MAIN 100
|
||||
#define ZY_MAIN 22
|
||||
#define ZH_CREATURES 50
|
||||
#define Z_CARDWIDTH 30
|
||||
#define Z_CARDHEIGHT 40
|
||||
#define Z_MAIN_NBCARDS 7
|
||||
#define Z_SPELLS_NBCARDS 3
|
||||
#define ZX_SPELL 450
|
||||
#define ZY_SPELL 22
|
||||
|
||||
|
||||
|
||||
|
||||
MTGGuiPlay::MTGGuiPlay(int id, GameObserver * _game):PlayGuiObjectController(id, _game){
|
||||
currentPlayer = NULL;
|
||||
offset = 0;
|
||||
|
||||
|
||||
mPhaseBarTexture = JRenderer::GetInstance()->LoadTexture("graphics/phasebar.png", TEX_TYPE_USE_VRAM);
|
||||
for (int i=0; i < 12; i++){
|
||||
phaseIcons[2*i] = NEW JQuad(mPhaseBarTexture, i*28, 0, 28, 28);
|
||||
phaseIcons[2*i + 1] = NEW JQuad(mPhaseBarTexture, i*28, 28, 28, 28);
|
||||
}
|
||||
mGlitter = NEW JQuad(mPhaseBarTexture, 392, 0, 5, 5);
|
||||
mGlitter->SetHotSpot(2.5,2.5);
|
||||
mGlitterAlpha = -1;
|
||||
mFont= GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
mFont->SetScale(0.75);
|
||||
|
||||
|
||||
mIconsTexture = JRenderer::GetInstance()->LoadTexture("graphics/menuicons.png", TEX_TYPE_USE_VRAM);
|
||||
//load all the icon images
|
||||
mIcons[MTG_COLOR_ARTIFACT] = NEW JQuad(mIconsTexture, 10 + 6*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_LAND] = NEW JQuad(mIconsTexture, 10 + 5*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_WHITE] = NEW JQuad(mIconsTexture, 10 + 4*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_RED] = NEW JQuad(mIconsTexture, 10 + 3*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_BLACK] = NEW JQuad(mIconsTexture, 10 + 2*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_BLUE] = NEW JQuad(mIconsTexture, 10 + 1*32, 32, 32, 32);
|
||||
mIcons[MTG_COLOR_GREEN] = NEW JQuad(mIconsTexture, 10 + 0*32, 32, 32, 32);
|
||||
for (int i=0; i < 7; i++){
|
||||
mIcons[i]->SetHotSpot(16,16);
|
||||
}
|
||||
|
||||
mBgTex = JRenderer::GetInstance()->LoadTexture("graphics/background.png", TEX_TYPE_USE_VRAM);
|
||||
mBg = NEW JQuad(mBgTex, 0, 0, 480, 272);
|
||||
|
||||
mBgTex2 = JRenderer::GetInstance()->LoadTexture("graphics/back.jpg", TEX_TYPE_USE_VRAM);
|
||||
mBg2 = NEW JQuad(mBgTex2, 0, 0, 480, 255);
|
||||
for (int i= 0; i < 4; i++){
|
||||
alphaBg[i] = 255;
|
||||
}
|
||||
alphaBg[0] = 0;
|
||||
AddPlayersGuiInfo();
|
||||
}
|
||||
|
||||
|
||||
CardGui * MTGGuiPlay::getByCard(MTGCardInstance * card){
|
||||
for (int i = offset; i < mCount; i++){
|
||||
CardGui * cardg = (CardGui *)mObjects[i];
|
||||
if(cardg && cardg->card == card){
|
||||
return cardg;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void MTGGuiPlay::initCardsDisplay(){
|
||||
for (int i = 0; i < SCREEN_WIDTH/5; i++){
|
||||
for(int j=0; j < SCREEN_HEIGHT/5; j++){
|
||||
cardsGrid[i][j] = NULL;
|
||||
}
|
||||
}
|
||||
cards_x_limit = 12;
|
||||
nb_creatures = 0;
|
||||
nb_lands = 0;
|
||||
nb_spells = 0;
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiPlay::adjustCardPosition(CardGui * cardg){
|
||||
int x5 = cardg->x / 5;
|
||||
int y5 = cardg->y / 5;
|
||||
|
||||
while (cardsGrid[x5][y5] && x5 <SCREEN_WIDTH/5 && y5 < SCREEN_HEIGHT/5 ){
|
||||
x5++;
|
||||
y5++;
|
||||
}
|
||||
cardg->x = x5 * 5;
|
||||
cardg->y = y5 * 5;
|
||||
cardsGrid[x5][y5] = cardg->card;
|
||||
}
|
||||
|
||||
void MTGGuiPlay::setCardPosition(CardGui * cardg, int player, int playerTurn, int spellMode){
|
||||
MTGCardInstance * card = cardg->card;
|
||||
if (card->target)
|
||||
return;
|
||||
if (spellMode && (card->isACreature() || card->hasType("land"))) return;
|
||||
if (!spellMode && !card->isACreature() && !card->hasType("land")) return;
|
||||
if (card->isACreature()){
|
||||
int x_offset = nb_creatures % cards_x_limit;
|
||||
int y_offset = nb_creatures / cards_x_limit;
|
||||
cardg->x= ZX_MAIN + (Z_CARDWIDTH * x_offset);
|
||||
cardg->y=ZY_MAIN + ZH_CREATURES + (Z_CARDHEIGHT * y_offset) + 100 * (1-player);
|
||||
nb_creatures++;
|
||||
|
||||
if (playerTurn){
|
||||
if (card->isAttacker()){
|
||||
cardg->y=122 + 30 * (1-player);
|
||||
}
|
||||
}else{
|
||||
if (card->isDefenser()){
|
||||
CardGui * targetg = getByCard(card->isDefenser());
|
||||
if (targetg) cardg->x = targetg->x;
|
||||
cardg->y=122 + 30 * (1-player);
|
||||
}
|
||||
}
|
||||
|
||||
}else if(card->hasType("land")){
|
||||
int x_offset = nb_lands % cards_x_limit;
|
||||
int y_offset = nb_lands/ cards_x_limit;
|
||||
cardg->x=ZX_MAIN + (Z_CARDWIDTH * x_offset);
|
||||
cardg->y=ZY_MAIN + (Z_CARDHEIGHT * y_offset) + 200 * (1-player);
|
||||
nb_lands++;
|
||||
}else{
|
||||
int y_offset = nb_spells % Z_SPELLS_NBCARDS;
|
||||
int x_offset = nb_spells/ Z_SPELLS_NBCARDS;
|
||||
cardg->x=ZX_SPELL - (Z_CARDWIDTH * x_offset);
|
||||
cardg->y=ZY_SPELL + (Z_CARDHEIGHT * y_offset) + 125 * (1-player);
|
||||
nb_spells++;
|
||||
cards_x_limit = 12 - (nb_spells + 2)/ Z_SPELLS_NBCARDS;
|
||||
}
|
||||
adjustCardPosition(cardg);
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiPlay::setTargettingCardPosition(CardGui * cardg, int player, int playerTurn){
|
||||
MTGCardInstance * card = cardg->card;
|
||||
MTGCardInstance * target = card->target;
|
||||
if (!target)
|
||||
return;
|
||||
CardGui * targetg = getByCard(target);
|
||||
if (targetg){
|
||||
cardg->y=targetg->y + 5;
|
||||
cardg->x=targetg->x + 5;
|
||||
}
|
||||
adjustCardPosition(cardg);
|
||||
return;
|
||||
}
|
||||
|
||||
void MTGGuiPlay::updateCards(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
Player * player = game->players[0];
|
||||
int player0Mode =(game->currentPlayer == player);
|
||||
int nb_cards = player->game->inPlay->nb_cards;
|
||||
MTGCardInstance * attackers[MAX_ATTACKERS];
|
||||
for (int i = 0; i <MAX_ATTACKERS; i++){
|
||||
attackers[i] = NULL;
|
||||
}
|
||||
|
||||
offset = 6;
|
||||
|
||||
Player * opponent = game->players[1];
|
||||
int opponent_cards = opponent ->game->inPlay->nb_cards;
|
||||
if (mCount - offset != (nb_cards+opponent_cards) || game->currentPlayer != currentPlayer ){ //if the number of cards has changed, then an update occured (is this test engouh ?)
|
||||
resetObjects();
|
||||
AddPlayersGuiInfo();
|
||||
offset = mCount;
|
||||
|
||||
bool hasFocus = player0Mode;
|
||||
|
||||
for (int i = 0;i<nb_cards; i++){
|
||||
if (hasFocus) mCurr = mCount ;
|
||||
CardGui * object = NEW CardGui(mCount, player->game->inPlay->cards[i],40, i*35 + 10, 200, hasFocus);
|
||||
Add(object);
|
||||
hasFocus = false;
|
||||
}
|
||||
hasFocus = !player0Mode;
|
||||
for (int i = 0;i<opponent_cards; i++){
|
||||
if (hasFocus) mCurr = mCount ;
|
||||
CardGui * object = NEW CardGui(mCount, opponent->game->inPlay->cards[i],40, i*35 + 10, 10, hasFocus);
|
||||
Add(object);
|
||||
hasFocus = false;
|
||||
}
|
||||
|
||||
currentPlayer = game->currentPlayer;
|
||||
}
|
||||
|
||||
|
||||
//This is just so that we display the cards of the current player first, so that blockers are correctly positionned
|
||||
for (int j= 0; j < 2; j++){
|
||||
initCardsDisplay();
|
||||
if (j != player0Mode){
|
||||
for (int i =0; i<nb_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[i + offset];
|
||||
setCardPosition(cardGui, 0, player0Mode, 1);
|
||||
}
|
||||
for (int i =0; i<nb_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[i + offset];
|
||||
setCardPosition(cardGui, 0, player0Mode, 0);
|
||||
}
|
||||
}else{
|
||||
for (int i =0; i<opponent_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[nb_cards + i + offset];
|
||||
setCardPosition(cardGui, 1, !player0Mode,1);
|
||||
}
|
||||
for (int i =0; i<opponent_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[nb_cards + i + offset];
|
||||
setCardPosition(cardGui, 1, !player0Mode,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i =0; i<nb_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[i + offset ];
|
||||
setTargettingCardPosition(cardGui, 0, player0Mode);
|
||||
}
|
||||
|
||||
for (int i =0; i<opponent_cards; i++){
|
||||
CardGui * cardGui = (CardGui *)mObjects[nb_cards + i + offset];
|
||||
setTargettingCardPosition(cardGui, 1, !player0Mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiPlay::AddPlayersGuiInfo(){
|
||||
//init with the players objects
|
||||
if (mCount == 0){
|
||||
Add(NEW GuiAvatar(-1,50,2,155,false, GameObserver::GetInstance()->players[0]));
|
||||
Add(NEW GuiAvatar(-2,50,2,30,false,GameObserver::GetInstance()->players[1]));
|
||||
|
||||
Add(NEW GuiGraveyard(-3,30,40,150,false, GameObserver::GetInstance()->players[0]));
|
||||
Add(NEW GuiLibrary(-4,30,40,180,false, GameObserver::GetInstance()->players[0]));
|
||||
|
||||
|
||||
Add(NEW GuiGraveyard(-5,30,40,30,false, GameObserver::GetInstance()->players[1]));
|
||||
Add(NEW GuiLibrary(-6,30,40,60,false, GameObserver::GetInstance()->players[1]));
|
||||
}
|
||||
}
|
||||
|
||||
void MTGGuiPlay::Update(float dt){
|
||||
updateCards();
|
||||
PlayGuiObjectController::Update(dt);
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MTGGuiPlay::CheckUserInput(float dt){
|
||||
for (int i = 2; i<6;i++){
|
||||
GuiGameZone * zone = (GuiGameZone *)mObjects[i];
|
||||
if (zone->showCards){
|
||||
zone->cd->CheckUserInput(dt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PlayGuiObjectController::CheckUserInput(dt);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiPlay::RenderPlayerInfo(int playerid){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
JRenderer * r = JRenderer::GetInstance();
|
||||
Player * player = GameObserver::GetInstance()->players[playerid];
|
||||
int life = player->life;
|
||||
|
||||
//Avatar
|
||||
GuiAvatar * avatar = (GuiAvatar *)mObjects[3*playerid];
|
||||
avatar->Render();
|
||||
|
||||
|
||||
|
||||
//Mana
|
||||
ManaCost * cost = player->getManaPool();
|
||||
int nbicons = 0;
|
||||
for (int j=0; j<6;j++){
|
||||
int value = cost->getCost(j);
|
||||
for (int i=0; i<value; i++){
|
||||
float x = 10 + (nbicons %4) * 15;
|
||||
float y = 90 + 125 * (1-playerid) + (15 * (nbicons / 4));
|
||||
r->RenderQuad(mIcons[j],x,y,0,0.5, 0.5);
|
||||
nbicons++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MTGGuiPlay::RenderPhaseBar(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
int currentPhase = game->getCurrentGamePhase();
|
||||
for (int i=0; i < 12; i++){
|
||||
int index = 2*i + 1 ;
|
||||
if (i==currentPhase){
|
||||
index-=1;
|
||||
}
|
||||
renderer->RenderQuad(phaseIcons[index], 200 + 14*i,0,0,0.5,0.5);
|
||||
}
|
||||
mFont->SetScale(0.70);
|
||||
if (game->currentlyActing()->isAI()){
|
||||
mFont->SetColor(ARGB(255,128,128,128));
|
||||
}else{
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
mFont->DrawString(MTGPhaseNames[currentPhase], 375, 0);
|
||||
}
|
||||
|
||||
void MTGGuiPlay::Render(){
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
|
||||
//alphaBg[1] = 255;
|
||||
//alphaBg[2]= 255;
|
||||
//alphaBg[3] = 255;
|
||||
//mBg2->SetColor(ARGB(alphaBg[0], alphaBg[1],alphaBg[2],alphaBg[3]));
|
||||
renderer->RenderQuad(mBg2,0,17);
|
||||
|
||||
if (game->currentGamePhase >=MTG_PHASE_COMBATBEGIN && game->currentGamePhase < MTG_PHASE_COMBATEND){
|
||||
if (alphaBg[0] < 50){
|
||||
alphaBg[3]-=12;
|
||||
alphaBg[2]-=12;
|
||||
alphaBg[0]+=3;
|
||||
}
|
||||
alphaBg[1] = 255;
|
||||
|
||||
}else{
|
||||
if (alphaBg[0]){
|
||||
alphaBg[0]-=3;
|
||||
alphaBg[3]+=12;
|
||||
alphaBg[2]+=12;
|
||||
}
|
||||
alphaBg[1] = 255;
|
||||
}
|
||||
renderer->FillRect(0,0,480,272,ARGB(alphaBg[0], alphaBg[1],alphaBg[2],alphaBg[3]));
|
||||
|
||||
renderer->RenderQuad(mBg,0,0);
|
||||
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL && i!=mCurr){
|
||||
mObjects[i]->Render();
|
||||
}
|
||||
}
|
||||
|
||||
RenderPhaseBar();
|
||||
RenderPlayerInfo(0);
|
||||
RenderPlayerInfo(1);
|
||||
|
||||
if (mCount && mObjects[mCurr] != NULL){
|
||||
mObjects[mCurr]->Render();
|
||||
if (hasFocus && mCurr >= offset && showBigCards)
|
||||
((CardGui *)mObjects[mCurr])->RenderBig();
|
||||
}
|
||||
|
||||
if (mGlitterAlpha < 0){
|
||||
mGlitterAlpha = 510;
|
||||
int position = rand() % 2;
|
||||
if (position){
|
||||
mGlitterX = 65 + rand() % (420);
|
||||
mGlitterY = 17 + rand() % (5);
|
||||
}else{
|
||||
mGlitterX = 65 + rand() % (5);
|
||||
mGlitterY = 15 + rand() % (250);
|
||||
}
|
||||
}
|
||||
mGlitter->SetColor(ARGB((255-abs(255-mGlitterAlpha)),240,240,255));
|
||||
renderer->RenderQuad(mGlitter,mGlitterX,mGlitterY, (float)(mGlitterAlpha)/(float)255, 1.2*float(mGlitterAlpha)/float(255),1.2*float(mGlitterAlpha)/float(255));
|
||||
mGlitterAlpha-=10;
|
||||
|
||||
}
|
||||
|
||||
MTGGuiPlay::~MTGGuiPlay(){
|
||||
LOG("==Destroying MTGGuiPlay==");
|
||||
delete mBg;
|
||||
delete mBgTex;
|
||||
for (int i=0; i < 7; i++){
|
||||
delete mIcons[i];
|
||||
}
|
||||
delete mIconsTexture;
|
||||
delete mGlitter;
|
||||
for (int i=0; i < 12; i++){
|
||||
delete phaseIcons[2*i] ;
|
||||
delete phaseIcons[2*i + 1];
|
||||
}
|
||||
delete mPhaseBarTexture;
|
||||
|
||||
SAFE_DELETE(mBg2);
|
||||
SAFE_DELETE(mBgTex2);
|
||||
|
||||
LOG("==Destroying MTGGuiPlay Successful==");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MTGRules.h"
|
||||
|
||||
MTGAttackRule::MTGAttackRule(int _id):MTGAbility(_id,NULL){
|
||||
}
|
||||
|
||||
int MTGAttackRule::isReactingToClick(MTGCardInstance * card){
|
||||
if (currentPhase == MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && !card->isAttacker()){
|
||||
if (card->canAttack()) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGAttackRule::reactToClick(MTGCardInstance * card){
|
||||
if (!isReactingToClick(card)) return 0;
|
||||
card->attacker = 1;
|
||||
if (!card->basicAbilities[VIGILANCE]) card->tapped = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//The Attack rule is never destroyed
|
||||
int MTGAttackRule::testDestroy(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){
|
||||
}
|
||||
|
||||
int MTGBlockRule::isReactingToClick(MTGCardInstance * card){
|
||||
if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->opponent()){
|
||||
if (card->canBlock()) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGBlockRule::reactToClick(MTGCardInstance * card){
|
||||
if (!isReactingToClick(card)) return 0;
|
||||
MTGCardInstance * currentOpponent = card->isDefenser();
|
||||
|
||||
bool result = false;
|
||||
int candefend = 0;
|
||||
while (!result){
|
||||
currentOpponent = game->currentPlayer->game->inPlay->getNextAttacker(currentOpponent);
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf,"Defenser Toggle %s \n" ,card->model->getName());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
candefend = card->toggleDefenser(currentOpponent);
|
||||
result = (candefend || currentOpponent == NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//The Block rule is never destroyed
|
||||
int MTGBlockRule::testDestroy(){
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "MTGSpellStack.h"
|
||||
|
||||
MTGSpellStack::MTGSpellStack(){
|
||||
cursor = -1;
|
||||
}
|
||||
|
||||
void MTGSpellStack::addSpell(Ability * ability){
|
||||
cursor++;
|
||||
spellStack[cursor] ability;
|
||||
}
|
||||
|
||||
int MTGSpellStack::resolve(){
|
||||
if (cursor < 0)
|
||||
return 0;
|
||||
int result = cursor;
|
||||
cursor--;
|
||||
(spellStack[cursor + 1])->resolve();
|
||||
return (result+1);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "MTGCardInstance.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//Card Instance
|
||||
//--------------------------------------------
|
||||
MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to): model(card){
|
||||
belongs_to = _belongs_to;
|
||||
}
|
||||
|
||||
int MTGCardInstance::isInPlay(){
|
||||
return belongs_to->isInPlay(this);
|
||||
}
|
||||
|
||||
|
||||
JQuad * MTGCardInstance::getQuad(TexturesCache * cache){
|
||||
return model->getQuad(cache);
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Logger.h"
|
||||
#include "../include/ManaCost.h"
|
||||
#include "../include/ManaCostHybrid.h"
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
#endif
|
||||
ManaCost * manaCost;
|
||||
if (_manaCost){
|
||||
manaCost = _manaCost;
|
||||
}else{
|
||||
manaCost = NEW ManaCost();
|
||||
}
|
||||
int state = 0;
|
||||
unsigned int start = 0;
|
||||
unsigned int end = 0;
|
||||
while (!s.empty() && state != -1){
|
||||
switch(state){
|
||||
case 0:
|
||||
start = s.find_first_of("{");
|
||||
if (start == string::npos){
|
||||
return manaCost;
|
||||
}else{
|
||||
state = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
end = s.find_first_of("}");
|
||||
if (end == string::npos){
|
||||
state = -1;
|
||||
}else{
|
||||
string value = s.substr(start+1, end - 1 - start);
|
||||
if (value == "u"){
|
||||
manaCost->add(MTG_COLOR_BLUE, 1);
|
||||
}else if (value == "b"){
|
||||
manaCost->add(MTG_COLOR_BLACK, 1);
|
||||
}else if (value == "w"){
|
||||
manaCost->add(MTG_COLOR_WHITE, 1);
|
||||
}else if (value == "g"){
|
||||
manaCost->add(MTG_COLOR_GREEN, 1);
|
||||
}else if (value == "r"){
|
||||
manaCost->add(MTG_COLOR_RED, 1);
|
||||
}else if (value == "x"){
|
||||
manaCost->x();
|
||||
}else if (value == "t"){
|
||||
}else{
|
||||
int intvalue = atoi(value.c_str());
|
||||
int colors[2];
|
||||
int values[2];
|
||||
if (!intvalue && value.size() > 1){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Hybrid Mana ???\n");
|
||||
#endif
|
||||
for (int i = 0; i < 2; i++){
|
||||
char c = value[i];
|
||||
if (c >='0' && c <='9'){
|
||||
colors[i] = MTG_COLOR_ARTIFACT;
|
||||
values[i] = c - '0';
|
||||
}else{
|
||||
for (int j = 0; j < MTG_NB_COLORS; j++){
|
||||
if (c == MTGColorChars[j]){
|
||||
colors[i] = j;
|
||||
values[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
manaCost->addHybrid(colors[0], values[0], colors[1], values[1]);
|
||||
}else{
|
||||
manaCost->add(MTG_COLOR_ARTIFACT, intvalue);
|
||||
}
|
||||
}
|
||||
s = s.substr(end + 1);
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return manaCost;
|
||||
}
|
||||
|
||||
ManaCost::ManaCost(){
|
||||
init();
|
||||
}
|
||||
ManaCost::ManaCost(int _cost[], int nb_elems){
|
||||
init();
|
||||
int i;
|
||||
int total = nb_elems;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Create New MAnaCost, total Colors : %i\n", total);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
for (i = 0; i < total; i++){
|
||||
cost[_cost[i*2]] = _cost[i*2 + 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ManaCost::ManaCost(ManaCost * _manaCost){
|
||||
init();
|
||||
int i;
|
||||
for (i=0; i<= MTG_NB_COLORS; i++){
|
||||
cost[i] = _manaCost->getCost(i);
|
||||
}
|
||||
}
|
||||
|
||||
ManaCost::~ManaCost(){
|
||||
LOG("==Deleting ManaCost==");
|
||||
for (int i = 0; i < nbhybrids ; i++){
|
||||
SAFE_DELETE(hybrids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ManaCost::x(){
|
||||
cost[MTG_NB_COLORS] = 1;
|
||||
}
|
||||
|
||||
void ManaCost::init(){
|
||||
int i;
|
||||
for (i=0; i<= MTG_NB_COLORS; i++){
|
||||
cost[i] = 0;
|
||||
}
|
||||
nbhybrids = 0;
|
||||
}
|
||||
|
||||
|
||||
void ManaCost::copy(ManaCost * _manaCost){
|
||||
for (int i=0; i<= MTG_NB_COLORS; i++){
|
||||
cost[i] = _manaCost->getCost(i);
|
||||
}
|
||||
for (int i=0; i< _manaCost->nbhybrids; i++){
|
||||
hybrids[i] = NEW ManaCostHybrid((*_manaCost->hybrids[i]));
|
||||
}
|
||||
nbhybrids = _manaCost->nbhybrids;
|
||||
}
|
||||
|
||||
int ManaCost::getCost(int color){
|
||||
return cost[color];
|
||||
}
|
||||
|
||||
int ManaCost::getMainColor(){
|
||||
for (int i=0; i< MTG_NB_COLORS; i++){
|
||||
if (cost[i]) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ManaCost::hasColor(int color){
|
||||
if (cost[color]) return 1;
|
||||
for (int i = 0; i < nbhybrids; i++){
|
||||
if (hybrids[i]->hasColor(color)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ManaCost::getConvertedCost(){
|
||||
int result = 0;
|
||||
for (int i=0; i< MTG_NB_COLORS; i++){
|
||||
result += cost[i];
|
||||
}
|
||||
for (int i = 0; i < nbhybrids; i++){
|
||||
result+= hybrids[i]->getConvertedCost();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ManaCost::remove(int color, int value){
|
||||
cost[color] -= value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ManaCost::add(int color, int value){
|
||||
cost[color] += value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ManaCost::add(ManaCost * _cost){
|
||||
for (int i=0; i< MTG_NB_COLORS; i++){
|
||||
cost[i]+= _cost->getCost(i);
|
||||
}
|
||||
for (int i=0; i< _cost->nbhybrids; i++){
|
||||
hybrids[nbhybrids] = NEW ManaCostHybrid((*_cost->hybrids[i]));
|
||||
nbhybrids++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
string ManaCost::toString(){
|
||||
return "ManaCost - Todo";
|
||||
}
|
||||
|
||||
|
||||
int ManaCost::addHybrid(int c1, int v1, int c2, int v2){
|
||||
ManaCostHybrid * h = NEW ManaCostHybrid(c1,v1,c2,v2);
|
||||
hybrids[nbhybrids] = h;
|
||||
nbhybrids++;
|
||||
return nbhybrids;
|
||||
}
|
||||
|
||||
int ManaCost::pay(ManaCost * _cost){
|
||||
ManaCost * diff = Diff(_cost);
|
||||
for (int i=0; i < MTG_NB_COLORS; i++){
|
||||
cost[i] = diff->getCost(i);
|
||||
}
|
||||
delete diff;
|
||||
return 1;
|
||||
//TODO return 0 if can't afford the cost!
|
||||
}
|
||||
|
||||
//return 1 if _cost can be paid with current data
|
||||
int ManaCost::canAfford(ManaCost * _cost){
|
||||
ManaCost * diff = Diff(_cost);
|
||||
int positive = diff->isPositive();
|
||||
delete diff;
|
||||
if (positive){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("can afford\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ManaCost::isPositive(){
|
||||
for (int i=0; i < MTG_NB_COLORS; i++){
|
||||
|
||||
if (cost[i] < 0){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ManaCost::randomDiffHybrids(ManaCost * _cost, int diff[]){
|
||||
int _nbhybrids = _cost->nbhybrids;
|
||||
for (int i = 0; i < _nbhybrids; i++){
|
||||
ManaCostHybrid * h = _cost->hybrids[i];
|
||||
diff[h->color1 * 2 +1]-= h->value1;
|
||||
}
|
||||
}
|
||||
|
||||
int ManaCost::tryToPayHybrids(ManaCostHybrid * _hybrids[], int _nbhybrids, int diff[]){
|
||||
if (!_nbhybrids) return 1;
|
||||
int result = 0;
|
||||
ManaCostHybrid * h = _hybrids[_nbhybrids -1];
|
||||
if (diff[h->color1 * 2 +1] >= h->value1){
|
||||
diff[h->color1 * 2 +1]-= h->value1;
|
||||
result = tryToPayHybrids(_hybrids,_nbhybrids -1, diff);
|
||||
if (result) return 1;
|
||||
diff[h->color1 * 2 +1]+= h->value1;
|
||||
}
|
||||
if (diff[h->color2 * 2 +1] >= h->value2){
|
||||
diff[h->color2 * 2 +1]-= h->value2;
|
||||
result = tryToPayHybrids(_hybrids,_nbhybrids -1, diff);
|
||||
if (result) return 1;
|
||||
diff[h->color2 * 2 +1]+= h->value2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//compute the difference between two mana costs
|
||||
ManaCost * ManaCost::Diff(ManaCost * _cost){
|
||||
int diff[(MTG_NB_COLORS + 1 )* 2];
|
||||
diff[MTG_NB_COLORS * 2] = MTG_NB_COLORS;
|
||||
for (int i=0; i < MTG_NB_COLORS; i++){
|
||||
diff[i*2] = i;
|
||||
diff[i*2 +1] = cost[i] - _cost->getCost(i);
|
||||
}
|
||||
int hybridResult = tryToPayHybrids(_cost->hybrids, _cost->nbhybrids, diff);
|
||||
if (!hybridResult) randomDiffHybrids(_cost,diff);
|
||||
|
||||
//Colorless mana, special case
|
||||
int colorless_idx = MTG_COLOR_ARTIFACT * 2 + 1;
|
||||
if (diff[colorless_idx] < 0){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
//char buf[4096], *p = buf;
|
||||
//sprintf(buf, "--Diff color TEST %i : %i\n", i, cost[i]);
|
||||
OutputDebugString("Colorless mana not enough\n");
|
||||
#endif
|
||||
for (int i=0; i < MTG_NB_COLORS; i++){
|
||||
if (diff[i*2 + 1] > 0){
|
||||
if (diff[i*2 + 1] + diff[colorless_idx] > 0){
|
||||
diff[i*2 + 1] += diff[colorless_idx];
|
||||
diff[colorless_idx] = 0;
|
||||
break;
|
||||
}else{
|
||||
diff[colorless_idx] += diff[i*2 + 1];
|
||||
diff[i*2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Cost X
|
||||
if (_cost->getCost(MTG_NB_COLORS)){
|
||||
diff[MTG_NB_COLORS * 2 + 1] = 0;
|
||||
for (int i=0; i < MTG_NB_COLORS; i++){
|
||||
if (diff[i*2 + 1] > 0){
|
||||
diff[MTG_NB_COLORS * 2 + 1] += diff[i*2 + 1];
|
||||
diff[i*2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ManaCost * result = NEW ManaCost(diff, MTG_NB_COLORS +1);
|
||||
return result;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "../include/ManaCostHybrid.h"
|
||||
|
||||
ManaCostHybrid::ManaCostHybrid(){
|
||||
init(0,0,0,0);
|
||||
}
|
||||
|
||||
ManaCostHybrid::ManaCostHybrid(int c1,int v1,int c2,int v2){
|
||||
init(c1,v1,c2,v2);
|
||||
}
|
||||
|
||||
void ManaCostHybrid::init(int c1,int v1,int c2,int v2){
|
||||
color1 = c1;
|
||||
color2 = c2;
|
||||
value1 = v1;
|
||||
value2 = v2;
|
||||
}
|
||||
|
||||
int ManaCostHybrid::getConvertedCost(){
|
||||
if (value2 > value1) return value2;
|
||||
return value1;
|
||||
}
|
||||
|
||||
int ManaCostHybrid::hasColor(int color){
|
||||
if (((color1 == color) && value1) || ((color2 == color) && value2)) return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/MenuItem.h"
|
||||
|
||||
|
||||
MenuItem::MenuItem(int id, JLBFont *font, const char* text, int x, int y, JQuad * _off, JQuad * _on, const char * particle, JQuad * particleTex, bool hasFocus): JGuiObject(id), mFont(font), mText(text), mX(x), mY(y)
|
||||
{
|
||||
|
||||
|
||||
|
||||
updatedSinceLastRender = 1;
|
||||
mParticleSys = NEW hgeParticleSystem(particle, particleTex);
|
||||
mParticleSys->MoveTo(mX, mY);
|
||||
|
||||
|
||||
mHasFocus = hasFocus;
|
||||
lastDt = 0.001f;
|
||||
mScale = 1.0f;
|
||||
mTargetScale = 1.0f;
|
||||
|
||||
onQuad = _on;
|
||||
offQuad = _off;
|
||||
|
||||
if (hasFocus)
|
||||
Entering();
|
||||
mFont->SetScale(1.2f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MenuItem::Render()
|
||||
{
|
||||
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
|
||||
|
||||
if (mHasFocus)
|
||||
{
|
||||
if (!updatedSinceLastRender){
|
||||
mParticleSys->Update(lastDt);
|
||||
}
|
||||
// set additive blending
|
||||
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE);
|
||||
mParticleSys->Render();
|
||||
// set normal blending
|
||||
renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
onQuad->SetColor(ARGB(70,255,255,255));
|
||||
renderer->RenderQuad(onQuad, SCREEN_WIDTH , SCREEN_HEIGHT/2 , 0,8,8);
|
||||
onQuad->SetColor(ARGB(255,255,255,255));
|
||||
mFont->DrawString(mText, SCREEN_WIDTH/2, 3*SCREEN_HEIGHT/4, JGETEXT_CENTER);
|
||||
renderer->RenderQuad(onQuad, mX , mY , 0,mScale,mScale);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer->RenderQuad(offQuad, mX , mY , 0,mScale,mScale);
|
||||
}
|
||||
updatedSinceLastRender= 0;
|
||||
}
|
||||
|
||||
void MenuItem::Update(float dt)
|
||||
{
|
||||
updatedSinceLastRender = 1;
|
||||
lastDt = dt;
|
||||
if (mScale < mTargetScale)
|
||||
{
|
||||
mScale += 8.0f*dt;
|
||||
if (mScale > mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
else if (mScale > mTargetScale)
|
||||
{
|
||||
mScale -= 8.0f*dt;
|
||||
if (mScale < mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
|
||||
if (mHasFocus){
|
||||
mParticleSys->Update(dt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MenuItem::Entering()
|
||||
{
|
||||
|
||||
mParticleSys->Fire();
|
||||
mHasFocus = true;
|
||||
mTargetScale = 1.3f;
|
||||
}
|
||||
|
||||
|
||||
bool MenuItem::Leaving(u32 key)
|
||||
{
|
||||
mParticleSys->Stop(true);
|
||||
mHasFocus = false;
|
||||
mTargetScale = 1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MenuItem::ButtonPressed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MenuItem::~MenuItem(){
|
||||
if (mParticleSys) delete mParticleSys;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "../include/OptionItem.h"
|
||||
#include "../include/GameApp.h"
|
||||
#include <JGE.h>
|
||||
#include "../include/GameOptions.h"
|
||||
|
||||
|
||||
OptionItem::OptionItem(int _id, string _displayValue, int _maxValue, int _increment):JGuiObject(0){
|
||||
id = _id;
|
||||
maxValue = _maxValue;
|
||||
increment = _increment;
|
||||
displayValue = _displayValue;
|
||||
value = GameOptions::GetInstance()->values[id];
|
||||
hasFocus = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
OptionItem::~OptionItem(){
|
||||
//TODO
|
||||
}
|
||||
|
||||
void OptionItem::setData(){
|
||||
GameOptions::GetInstance()->values[id] = value;
|
||||
}
|
||||
|
||||
void OptionItem::Render(){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
if (hasFocus){
|
||||
mFont->SetColor(ARGB(255,255,255,0));
|
||||
}else{
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
mFont->DrawString(displayValue.c_str(),x,y);
|
||||
char buf[512];
|
||||
sprintf(buf, "%i", value);
|
||||
mFont->DrawString(buf,SCREEN_WIDTH -10 ,y,JGETEXT_RIGHT);
|
||||
}
|
||||
|
||||
void OptionItem::Update(float dt){
|
||||
JGE * mEngine = JGE::GetInstance();
|
||||
if (hasFocus){
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) updateValue();
|
||||
}
|
||||
}
|
||||
|
||||
void OptionItem::Entering(){
|
||||
hasFocus = true;
|
||||
}
|
||||
bool OptionItem::Leaving(){
|
||||
hasFocus = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
OptionItem * options[20];
|
||||
int nbitems;
|
||||
OptionsList::OptionsList(){
|
||||
nbitems = 0;
|
||||
current = -1;
|
||||
}
|
||||
OptionsList::~OptionsList(){
|
||||
for (int i = 0 ; i < nbitems; i++){
|
||||
SAFE_DELETE(options[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsList::Add(OptionItem * item){
|
||||
if (nbitems < 20){
|
||||
options[nbitems] = item;
|
||||
item->x = 10;
|
||||
item->y = 20 + 30*nbitems;
|
||||
nbitems++;
|
||||
if (current < 0){
|
||||
current = 0;
|
||||
options[0]->Entering();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsList::Render(){
|
||||
if (!nbitems){
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
|
||||
mFont->DrawString("NO OPTIONS AVAILABLE",SCREEN_WIDTH/2, 5, JGETEXT_RIGHT);
|
||||
}
|
||||
for (int i = 0 ; i < nbitems; i++){
|
||||
options[i]->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsList::save(){
|
||||
for (int i = 0; i < nbitems; i++){
|
||||
options[i]->setData();
|
||||
}
|
||||
GameOptions::GetInstance()->save();
|
||||
}
|
||||
|
||||
void OptionsList::Update(float dt){
|
||||
JGE * mEngine = JGE::GetInstance();
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_UP))
|
||||
{
|
||||
if (current > 0){
|
||||
options[current]->Leaving();
|
||||
current--;
|
||||
options[current]->Entering();
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonClick(PSP_CTRL_DOWN))
|
||||
{
|
||||
if (current < nbitems -1){
|
||||
options[current]->Leaving();
|
||||
current++;
|
||||
options[current]->Entering();
|
||||
}
|
||||
}
|
||||
for (int i = 0 ; i < nbitems; i++){
|
||||
options[i]->Update(dt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/PlayGuiObject.h"
|
||||
|
||||
#include "../include/Player.h"
|
||||
#include "../include/MTGGameZones.h"
|
||||
#include "../include/CardDisplay.h"
|
||||
|
||||
PlayGuiObject::PlayGuiObject(int id, float desiredHeight,float _x, float _y, bool hasFocus): JGuiObject(id){
|
||||
defaultHeight = desiredHeight;
|
||||
mHeight = desiredHeight;
|
||||
x = _x;
|
||||
y = _y;
|
||||
mHasFocus = hasFocus;
|
||||
type = 0;
|
||||
wave = 0;
|
||||
}
|
||||
|
||||
|
||||
void PlayGuiObject::Update(float dt){
|
||||
if (mHasFocus && mHeight < defaultHeight * 1.2)
|
||||
{
|
||||
mHeight += defaultHeight*0.8f*dt;
|
||||
fprintf(stderr, "increasing size to %f - %d", mHeight, GetId() );
|
||||
|
||||
if (mHeight > defaultHeight * 1.2)
|
||||
mHeight = defaultHeight * 1.2;
|
||||
}
|
||||
else if (!mHasFocus && mHeight > defaultHeight)
|
||||
{
|
||||
mHeight -= defaultHeight*0.8f*dt;
|
||||
if (mHeight < defaultHeight)
|
||||
mHeight = defaultHeight;
|
||||
}
|
||||
wave = (wave +2) % 255;
|
||||
}
|
||||
|
||||
GuiAvatar::GuiAvatar(int id, float desiredHeight,float _x, float _y, bool hasFocus, Player * _player): PlayGuiObject(id, desiredHeight, _x, _y, hasFocus){
|
||||
player= _player;
|
||||
avatarRed = 255;
|
||||
currentLife = player->life;
|
||||
type = GUI_AVATAR;
|
||||
}
|
||||
|
||||
void GuiAvatar::Render(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
JRenderer * r = JRenderer::GetInstance();
|
||||
int life = player->life;
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
mFont->SetScale(0.75);
|
||||
|
||||
//Avatar
|
||||
int lifeDiff = life - currentLife;
|
||||
if (lifeDiff < 0 && currentLife >0 ){
|
||||
avatarRed = 192 + (3* 255 * lifeDiff)/ currentLife / 4;
|
||||
if (avatarRed<0)
|
||||
avatarRed = 0;
|
||||
}
|
||||
currentLife= life;
|
||||
|
||||
JQuad * quad = player->mAvatar;
|
||||
if(quad){
|
||||
quad->SetColor(ARGB(255,255,avatarRed,avatarRed));
|
||||
r->RenderQuad(quad,x,y);
|
||||
if (mHasFocus){
|
||||
r->FillRect(x,y,quad->mWidth,quad->mHeight,ARGB(abs(wave-128), 255,255,255));
|
||||
}
|
||||
}
|
||||
|
||||
if (avatarRed < 255){
|
||||
avatarRed+=3;
|
||||
if (avatarRed >255)
|
||||
avatarRed = 255;
|
||||
}
|
||||
if(game->currentPlayer == player){
|
||||
r->DrawRect(x-1,y-1 ,37,52,ARGB(255,0,255,0));
|
||||
}else if (game->currentActionPlayer == player){
|
||||
r->DrawRect(x,y,35,50,ARGB(255,0,0,255));
|
||||
}
|
||||
if(game->isInterrupting == player){
|
||||
r->DrawRect(x,y ,35,50,ARGB(255,255,0,0));
|
||||
}
|
||||
|
||||
//Life
|
||||
char buffer[5];
|
||||
sprintf(buffer, "%i",life);
|
||||
mFont->SetColor(ARGB(128,0,0,0));
|
||||
mFont->DrawString(buffer, x+3,y+40);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
mFont->DrawString(buffer, x+1,y+38);
|
||||
}
|
||||
|
||||
|
||||
void GuiGameZone::toggleDisplay(){
|
||||
if (showCards){
|
||||
showCards = 0;
|
||||
}else{
|
||||
showCards = 1;
|
||||
cd->init(zone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiGameZone::Render(){
|
||||
//Texture
|
||||
JQuad * quad = GameApp::CommonRes->GetQuad("back_thumb");
|
||||
float scale = defaultHeight / quad->mHeight;
|
||||
quad->SetColor(ARGB(255,255,255,255));
|
||||
|
||||
JRenderer::GetInstance()->RenderQuad(quad,x,y,0.0,scale, scale);
|
||||
if (mHasFocus){
|
||||
JRenderer::GetInstance()->FillRect(x,y,quad->mWidth*scale,quad->mHeight*scale,ARGB(abs(wave-128), 255,255,255));
|
||||
}
|
||||
//Number of cards
|
||||
JLBFont * mFont = GameApp::CommonRes->GetJLBFont(MAIN_FONT);
|
||||
char buffer[512];
|
||||
sprintf(buffer,"%i", zone->nb_cards);
|
||||
mFont->SetScale(0.75);
|
||||
mFont->SetColor(ARGB(128,0,0,0));
|
||||
mFont->DrawString(buffer, x+2, y+2);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
mFont->DrawString(buffer, x, y);
|
||||
|
||||
if (showCards) cd->Render();
|
||||
}
|
||||
|
||||
void GuiGameZone::ButtonPressed(int controllerId, int controlId){
|
||||
toggleDisplay();
|
||||
}
|
||||
|
||||
void GuiGameZone::Update(float dt){
|
||||
if (showCards) cd->Update(dt);
|
||||
PlayGuiObject::Update(dt);
|
||||
}
|
||||
|
||||
GuiGameZone::GuiGameZone(int id, float desiredHeight,float _x, float _y, bool hasFocus,MTGGameZone * _zone): PlayGuiObject(id, desiredHeight, _x, _y, hasFocus), zone(_zone){
|
||||
cd = NEW CardDisplay(id, GameObserver::GetInstance(), _x, _y, this);
|
||||
showCards = 0;
|
||||
}
|
||||
|
||||
GuiGameZone::~GuiGameZone(){
|
||||
if(cd) delete cd;
|
||||
}
|
||||
|
||||
GuiGraveyard::GuiGraveyard(int id, float desiredHeight,float _x, float _y, bool hasFocus,Player * player):GuiGameZone(id, desiredHeight, _x, _y, hasFocus,player->game->graveyard){
|
||||
type= GUI_GRAVEYARD;
|
||||
}
|
||||
|
||||
|
||||
GuiLibrary::GuiLibrary(int id, float desiredHeight,float _x, float _y, bool hasFocus,Player * player):GuiGameZone(id, desiredHeight, _x, _y, hasFocus,player->game->library){
|
||||
type = GUI_LIBRARY;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/PlayGuiObjectController.h"
|
||||
|
||||
#include "../include/PlayGuiObject.h"
|
||||
#include "../include/GameObserver.h"
|
||||
|
||||
bool PlayGuiObjectController::showBigCards = true;
|
||||
|
||||
int PlayGuiObjectController::getClosestItem(int direction){
|
||||
return getClosestItem(direction, 35);
|
||||
}
|
||||
|
||||
|
||||
int PlayGuiObjectController::getClosestItem(int direction, float tolerance){
|
||||
if (mCount == 0){
|
||||
return -1;
|
||||
}
|
||||
if (mCount == 1){
|
||||
return mCurr;
|
||||
}
|
||||
|
||||
float maxDist = SCREEN_WIDTH * SCREEN_WIDTH;
|
||||
PlayGuiObject * current = (PlayGuiObject *)mObjects[mCurr];
|
||||
int closest_match = -1;
|
||||
int available = 0;
|
||||
float x0, y0, x1, y1;
|
||||
x0 = current->x;
|
||||
y0 = current->y;
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (i == mCurr) continue;
|
||||
PlayGuiObject * other = (PlayGuiObject *) mObjects[i];
|
||||
x1 = other->x;
|
||||
y1 = other->y;
|
||||
float dist = (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1);
|
||||
if (dist>=maxDist) continue;
|
||||
//Potential match !
|
||||
int ok = 0;
|
||||
switch(direction){
|
||||
case DIR_DOWN:
|
||||
if (y1 > y0){
|
||||
available = 1;
|
||||
if (fabs(x0-x1) < tolerance ) ok = 1;
|
||||
}
|
||||
break;
|
||||
case DIR_UP:
|
||||
if (y1 < y0){
|
||||
available = 1;
|
||||
if (fabs(x0-x1) < tolerance ) ok = 1;
|
||||
}
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
if (x1 < x0){
|
||||
available = 1;
|
||||
if (fabs(y0-y1) < tolerance ) ok = 1;
|
||||
}
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
if (x1 > x0){
|
||||
available = 1;
|
||||
if (fabs(y0-y1) < tolerance ) ok = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ok){
|
||||
closest_match = i;
|
||||
maxDist = dist;
|
||||
}
|
||||
}
|
||||
if (closest_match == -1){
|
||||
if (available) return getClosestItem(direction,tolerance+5);
|
||||
return mCurr;
|
||||
}
|
||||
return closest_match;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int PlayGuiObjectController::getClosestItem(int direction, float tolerance){
|
||||
if (mCount == 0){
|
||||
return -1;
|
||||
}
|
||||
if (mCount == 1){
|
||||
return mCurr;
|
||||
}
|
||||
|
||||
float MaxTolerance = SCREEN_HEIGHT;
|
||||
PlayGuiObject * current = (PlayGuiObject *)mObjects[mCurr];
|
||||
int found = 0;
|
||||
int closest_match_id = -1;
|
||||
for (int i=0;i<mCount;i++){
|
||||
fprintf(stderr, "distance STEP 3-%i\n", i);
|
||||
if (i != mCurr){ //Don't wanna return the same object as currently selected
|
||||
if (closest_match_id == -1){
|
||||
closest_match_id = i;
|
||||
}
|
||||
if (mObjects[i]!=NULL){
|
||||
float x0, y0, x1, y1,closest;
|
||||
PlayGuiObject * closest_match = (PlayGuiObject *)mObjects[closest_match_id];
|
||||
PlayGuiObject * other = (PlayGuiObject *) mObjects[i];
|
||||
fprintf(stderr, "distance STEP 4-%i\n", i);
|
||||
switch(direction){
|
||||
case DIR_DOWN:
|
||||
x0 = current->x;
|
||||
y0 = current->y;
|
||||
x1 = other->x;
|
||||
y1 = other->y;
|
||||
closest = closest_match->y - y0;
|
||||
break;
|
||||
case DIR_UP:
|
||||
x0 = current->x;
|
||||
y0 = other->y;
|
||||
x1 = other->x;
|
||||
y1 = current->y;
|
||||
closest = y1 - closest_match->y;
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
MaxTolerance = SCREEN_WIDTH;
|
||||
x0 = current->y;
|
||||
y1 = current->x;
|
||||
x1 = other->y;
|
||||
y0 = other->x;
|
||||
closest = y1 - closest_match->x;
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
MaxTolerance = SCREEN_WIDTH;
|
||||
x0 = current->y;
|
||||
fprintf(stderr, "distance STEP 401\n");
|
||||
|
||||
y0 = current->x;
|
||||
fprintf(stderr, "distance STEP 402\n");
|
||||
x1 = other->y;
|
||||
fprintf(stderr, "distance STEP 403\n");
|
||||
y1 = other->x;
|
||||
fprintf(stderr, "distance STEP 404\n");
|
||||
closest = closest_match->x - y0;
|
||||
fprintf(stderr, "distance STEP 405\n");
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "distance STEP 5\n");
|
||||
float distance = y1-y0;
|
||||
float lateral_distance = fabs(x1-x0);
|
||||
fprintf(stderr, "distance STEP 6 \n");
|
||||
if (lateral_distance < tolerance){
|
||||
fprintf(stderr, "distance STEP 7\n");
|
||||
if (distance > 0 && (!found || (distance < closest && closest > 0 ))){
|
||||
|
||||
found = 1;
|
||||
closest_match_id = i;
|
||||
fprintf(stderr, "distance STEP 8\n");
|
||||
}
|
||||
}
|
||||
}// if (mObjects[i]!=NULL)
|
||||
}
|
||||
}
|
||||
if (!found){
|
||||
fprintf(stderr, "NOT FOUND !\n");
|
||||
if (tolerance < MaxTolerance){
|
||||
fprintf(stderr, "distance STEP 9\n");
|
||||
return getClosestItem(direction, tolerance + 5);
|
||||
}else{
|
||||
fprintf(stderr, "Closest Match ID: %i\n", mCurr);
|
||||
return mCurr;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Closest Match ID: %i\n", closest_match_id);
|
||||
return closest_match_id;
|
||||
|
||||
}
|
||||
*/
|
||||
void PlayGuiObjectController::Update(float dt){
|
||||
for (int i=0;i<mCount;i++){
|
||||
if (mObjects[i]!=NULL){
|
||||
mObjects[i]->Update(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PlayGuiObjectController::CheckUserInput(float dt){
|
||||
if (!mCount)
|
||||
return;
|
||||
if (game != NULL){
|
||||
if (mEngine->GetButtonClick(mActionButton)){
|
||||
if (mObjects[mCurr] != NULL && mObjects[mCurr]->ButtonPressed()){
|
||||
game->ButtonPressed(mId, (PlayGuiObject *)mObjects[mCurr]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mEngine->GetButtonClick(PSP_CTRL_CROSS)){
|
||||
game->cancelCurrentAction();
|
||||
}
|
||||
}
|
||||
|
||||
if (mEngine->GetButtonState(PSP_CTRL_LEFT))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_LEFT, dt))
|
||||
{
|
||||
int n = getClosestItem(DIR_LEFT);
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_LEFT))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonState(PSP_CTRL_RIGHT))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_RIGHT, dt))
|
||||
{
|
||||
int n = getClosestItem(DIR_RIGHT);
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_RIGHT))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonState(PSP_CTRL_UP))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_UP, dt))
|
||||
{
|
||||
int n = getClosestItem(DIR_UP);
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_UP))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mEngine->GetButtonState(PSP_CTRL_DOWN))
|
||||
{
|
||||
if (KeyRepeated(PSP_CTRL_DOWN, dt))
|
||||
{
|
||||
int n = getClosestItem(DIR_DOWN);
|
||||
if (n != mCurr && mObjects[mCurr] != NULL && mObjects[mCurr]->Leaving(PSP_CTRL_DOWN))
|
||||
{
|
||||
mCurr = n;
|
||||
mObjects[mCurr]->Entering();
|
||||
}
|
||||
}
|
||||
}else if (mEngine->GetButtonClick(PSP_CTRL_TRIANGLE)){
|
||||
showBigCards = !showBigCards;
|
||||
}
|
||||
|
||||
else{
|
||||
mLastKey = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Player.h"
|
||||
#include "../include/GameObserver.h"
|
||||
|
||||
|
||||
|
||||
Player::Player(MTGPlayerCards * _deck, char * file): Damageable(20){
|
||||
deckFile = file;
|
||||
game = _deck;
|
||||
game->setOwner(this);
|
||||
manaPool = NEW ManaCost();
|
||||
canPutLandsIntoPlay = 1;
|
||||
mAvatar = NULL;
|
||||
type_as_damageable = DAMAGEABLE_PLAYER;
|
||||
}
|
||||
|
||||
Player::~Player(){
|
||||
if (manaPool) delete manaPool;
|
||||
if (mAvatarTex) delete mAvatarTex;
|
||||
if (mAvatar) delete mAvatar;
|
||||
}
|
||||
|
||||
MTGInPlay * Player::inPlay(){
|
||||
return game->inPlay;
|
||||
}
|
||||
|
||||
int Player::getId(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
for (int i= 0; i < 2; i++){
|
||||
if (game->players[i] == this) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
JQuad * Player::getIcon(){
|
||||
return mAvatar;
|
||||
}
|
||||
|
||||
Player * Player::opponent(){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
for (int i= 0; i < 2; i++){
|
||||
if (game->players[i] != this) return game->players[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HumanPlayer::HumanPlayer(MTGPlayerCards * _deck, char * file):Player(_deck, file){
|
||||
mAvatarTex = JRenderer::GetInstance()->LoadTexture("player/avatar.jpg", TEX_TYPE_USE_VRAM);
|
||||
if (mAvatarTex)
|
||||
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
|
||||
}
|
||||
|
||||
ManaCost * Player::getManaPool(){
|
||||
return manaPool;
|
||||
}
|
||||
|
||||
int Player::manaBurn(){
|
||||
int burn = manaPool->getConvertedCost();
|
||||
life -= burn;
|
||||
manaPool->init();
|
||||
return burn;
|
||||
}
|
||||
|
||||
|
||||
int Player::testLife(){
|
||||
if (life <=0){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
//char buf[4096], *p = buf;
|
||||
//sprintf(buf, "--Diff color TEST %i : %i\n", i, cost[i]);
|
||||
OutputDebugString("GAME OVER\n");
|
||||
#endif
|
||||
//return GameObserver::GetInstance()->endOfGame();
|
||||
}
|
||||
return life;
|
||||
}
|
||||
|
||||
int Player::afterDamage(){
|
||||
return testLife();
|
||||
}
|
||||
|
||||
//Cleanup phase at the end of a turn
|
||||
void Player::cleanupPhase(){
|
||||
game->inPlay->cleanupPhase();
|
||||
game->graveyard->cleanupPhase();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/PlayerData.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
PlayerData::PlayerData(MTGAllCards * allcards){
|
||||
//CREDITS
|
||||
credits = 3000; //Default value
|
||||
std::ifstream file(PLAYER_SAVEFILE);
|
||||
std::string s;
|
||||
if(file){
|
||||
if(std::getline(file,s)){
|
||||
credits = atoi(s.c_str());
|
||||
}else{
|
||||
//TODO error management
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
//COLLECTION
|
||||
collection = NEW MTGDeck("Res/player/collection.dat", allcards->mCache , allcards);
|
||||
}
|
||||
|
||||
|
||||
int PlayerData::save(){
|
||||
std::ofstream file(PLAYER_SAVEFILE);
|
||||
char writer[10];
|
||||
if (file){
|
||||
sprintf(writer,"%i\n", credits);
|
||||
file<<writer;
|
||||
file.close();
|
||||
}
|
||||
collection->save();
|
||||
return 1;
|
||||
}
|
||||
|
||||
PlayerData::~PlayerData(){
|
||||
SAFE_DELETE(collection);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/PriceList.h"
|
||||
|
||||
|
||||
Price::Price(int _cardid, int _price): cardid(_cardid),price(_price){
|
||||
}
|
||||
|
||||
|
||||
|
||||
PriceList::PriceList(const char * _filename, MTGAllCards * _collection):collection(_collection){
|
||||
nbprices = 0;
|
||||
filename = _filename;
|
||||
std::ifstream file(_filename);
|
||||
std::string cardid;
|
||||
std::string price;
|
||||
if(file){
|
||||
while(std::getline(file,cardid)){
|
||||
std::getline(file,price);
|
||||
prices[nbprices]= NEW Price(atoi(cardid.c_str()), atoi(price.c_str()));
|
||||
nbprices++;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PriceList::~PriceList(){
|
||||
for (int i = 0; i < nbprices; i++){
|
||||
delete (prices[i]);
|
||||
}
|
||||
nbprices = 0;
|
||||
}
|
||||
|
||||
int PriceList::save(){
|
||||
std::ofstream file(filename.c_str());
|
||||
char writer[20];
|
||||
if (file){
|
||||
for (int i = 0; i<nbprices; i++){
|
||||
sprintf(writer,"%i\n%i\n", prices[i]->cardid, prices[i]->price);
|
||||
file<<writer;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
int PriceList::getPrice(int cardId){
|
||||
for(int i = 0; i < nbprices; i++){
|
||||
if (prices[i]->cardid == cardId){
|
||||
return prices[i]->price;
|
||||
}
|
||||
}
|
||||
char rarity = collection->getCardById(cardId)->getRarity();
|
||||
switch(rarity){
|
||||
case RARITY_M:
|
||||
return 3000;
|
||||
break;
|
||||
case RARITY_R:
|
||||
return 500;
|
||||
break;
|
||||
case RARITY_U:
|
||||
return 100;
|
||||
break;
|
||||
case RARITY_C:
|
||||
return 20;
|
||||
break;
|
||||
case RARITY_L:
|
||||
return 5;
|
||||
break;
|
||||
default:
|
||||
return 20;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int PriceList::setPrice(int cardId, int price){
|
||||
for(int i = 0; i < nbprices; i++){
|
||||
if (prices[i]->cardid == cardId){
|
||||
prices[i]->price = price;
|
||||
return prices[i]->price;
|
||||
}
|
||||
}
|
||||
prices[nbprices] = NEW Price(cardId, price);
|
||||
nbprices++;
|
||||
return prices[nbprices-1]->price;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/ShopItem.h"
|
||||
#include "../include/CardGui.h"
|
||||
|
||||
|
||||
ShopItem::ShopItem(int id, JLBFont *font, char* text, JQuad * _quad,JQuad * _thumb, int x, int y, bool hasFocus, int _price): JGuiObject(id), mFont(font), mText(text), mX(x), mY(y), quad(_quad), thumb(_thumb), price(_price)
|
||||
{
|
||||
quantity = 10;
|
||||
card = NULL;
|
||||
mHasFocus = hasFocus;
|
||||
|
||||
mScale = 1.0f;
|
||||
mTargetScale = 1.0f;
|
||||
|
||||
|
||||
|
||||
if (hasFocus)
|
||||
Entering();
|
||||
mFont->SetScale(1.2f);
|
||||
|
||||
}
|
||||
|
||||
ShopItem::ShopItem(int id, JLBFont *font, int _cardid, int x, int y, bool hasFocus, MTGAllCards * collection, int _price): JGuiObject(id), mFont(font), mX(x), mY(y), price(_price){
|
||||
mHasFocus = hasFocus;
|
||||
|
||||
mScale = 1.0f;
|
||||
mTargetScale = 1.0f;
|
||||
|
||||
|
||||
|
||||
if (hasFocus)
|
||||
Entering();
|
||||
mFont->SetScale(1.2f);
|
||||
|
||||
card = collection->getCardById(_cardid);
|
||||
quantity = 1;
|
||||
if (card->getRarity() == RARITY_L) quantity = 50;
|
||||
quad = NULL;
|
||||
thumb = NULL;
|
||||
}
|
||||
|
||||
|
||||
ShopItem::~ShopItem(){
|
||||
|
||||
}
|
||||
|
||||
const char * ShopItem::getText(){
|
||||
return mText.c_str();
|
||||
}
|
||||
|
||||
|
||||
void ShopItem::Render(){
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(mX-5, mY-5,230,35, ARGB(128,0,0,0));
|
||||
if (card){
|
||||
thumb = card->getThumb();
|
||||
mText= card->name;
|
||||
}
|
||||
|
||||
if (thumb){
|
||||
renderer->RenderQuad(thumb,mX,mY,0,mScale * 0.45,mScale * 0.45);
|
||||
}else{
|
||||
//NOTHING
|
||||
}
|
||||
if (mHasFocus){
|
||||
if (card){
|
||||
quad = card->getQuad();
|
||||
}
|
||||
if (quad){
|
||||
renderer->RenderQuad(quad,mX + SCREEN_WIDTH/2 + 20,5,0, 0.9f,0.9f);
|
||||
}else{
|
||||
if (card) CardGui::alternateRender(card,mFont,NULL,mX + SCREEN_WIDTH/2 + 100 + 20,133,0, 0.9f);
|
||||
//TODO
|
||||
}
|
||||
mFont->SetColor(ARGB(255,255,255,0));
|
||||
}else{
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
if (!quantity){
|
||||
mFont->SetColor(ARGB(255,128,128,128));
|
||||
}
|
||||
mFont->SetScale(mScale);
|
||||
mFont->DrawString(mText.c_str(),mX + 30,mY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ShopItem::Update(float dt)
|
||||
{
|
||||
if (mScale < mTargetScale)
|
||||
{
|
||||
mScale += 8.0f*dt;
|
||||
if (mScale > mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
else if (mScale > mTargetScale)
|
||||
{
|
||||
mScale -= 8.0f*dt;
|
||||
if (mScale < mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ShopItem::Entering()
|
||||
{
|
||||
|
||||
mHasFocus = true;
|
||||
mTargetScale = 1.2f;
|
||||
}
|
||||
|
||||
|
||||
bool ShopItem::Leaving(u32 key)
|
||||
{
|
||||
mHasFocus = false;
|
||||
mTargetScale = 1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ShopItem::ButtonPressed()
|
||||
{
|
||||
return (quantity >0);
|
||||
}
|
||||
|
||||
|
||||
ShopItems::ShopItems(int id, JGuiListener* listener, JLBFont* font, int x, int y, MTGAllCards * _collection, int _setId): JGuiController(id, listener), mX(x), mY(y), mFont(font), collection(_collection), setId(_setId){
|
||||
mHeight = 0;
|
||||
showPriceDialog = -1;
|
||||
dialog = NULL;
|
||||
pricelist = NEW PriceList("Res/settings/prices.dat",_collection);
|
||||
playerdata = NEW PlayerData(_collection);
|
||||
display = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShopItems::Add(int cardid){
|
||||
int rnd = (rand() % 20);
|
||||
int price = pricelist->getPrice(cardid);
|
||||
price = price + price * (rnd -10)/100;
|
||||
JGuiController::Add(NEW ShopItem(mCount, mFont, cardid, mX + 10, mY + 10 + mHeight, (mCount == 0),collection, price));
|
||||
mHeight += 40;
|
||||
}
|
||||
|
||||
void ShopItems::Add(char * text, JQuad * quad,JQuad * thumb, int price){
|
||||
JGuiController::Add(NEW ShopItem(mCount, mFont, text, quad, thumb, mX + 10, mY + 10 + mHeight, (mCount == 0), price));
|
||||
mHeight += 40;
|
||||
}
|
||||
|
||||
void ShopItems::Update(float dt){
|
||||
if (display){
|
||||
display->CheckUserInput(dt);
|
||||
if (display) display->Update(dt);
|
||||
}else{
|
||||
if (showPriceDialog!=-1){
|
||||
ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]);
|
||||
int price = item->price;
|
||||
char buffer[4096];
|
||||
sprintf(buffer,"%s : %i credits",item->getText(),price);
|
||||
if(!dialog){
|
||||
dialog = NEW SimpleMenu(1,this,mFont,SCREEN_WIDTH-300,SCREEN_HEIGHT/2,270,buffer);
|
||||
dialog->Add(1,"Yes");
|
||||
dialog->Add(2,"No");
|
||||
}
|
||||
else{
|
||||
dialog->Update(dt);
|
||||
}
|
||||
}else{
|
||||
SAFE_DELETE(dialog);
|
||||
JGuiController::Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ShopItems::Render(){
|
||||
JGuiController::Render();
|
||||
if (showPriceDialog==-1){
|
||||
|
||||
}else{
|
||||
if(dialog){
|
||||
dialog->Render();
|
||||
}
|
||||
}
|
||||
char credits[512];
|
||||
sprintf(credits,"credits: %i", playerdata->credits);
|
||||
mFont->SetScale(1.2);
|
||||
mFont->SetColor(ARGB(200,0,0,0));
|
||||
mFont->DrawString(credits,SCREEN_WIDTH-148, SCREEN_HEIGHT - 13);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
mFont->DrawString(credits,SCREEN_WIDTH-150, SCREEN_HEIGHT - 15);
|
||||
if (display) display->Render();
|
||||
}
|
||||
|
||||
void ShopItems::pricedialog(int id, int mode){
|
||||
if (mode){
|
||||
showPriceDialog = id;
|
||||
}else{
|
||||
showPriceDialog = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void ShopItems::ButtonPressed(int controllerId, int controlId){
|
||||
if (controllerId == 12){
|
||||
safeDeleteDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]);
|
||||
int price = item->price;
|
||||
switch(controlId){
|
||||
case 1:
|
||||
if (playerdata->credits >= price){
|
||||
playerdata->credits -= price;
|
||||
if (item->card){
|
||||
int rnd = (rand() % 5);
|
||||
price = price + (rnd * price)/100;
|
||||
pricelist->setPrice(item->card->getMTGId(),price);
|
||||
playerdata->collection->add(item->card);
|
||||
item->quantity--;
|
||||
}else{
|
||||
safeDeleteDisplay();
|
||||
display = new CardDisplay(12,NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT/2,this,NULL,5);
|
||||
int curNbcards = playerdata->collection->totalCards();
|
||||
if (showPriceDialog == 0){
|
||||
//Starter Deck
|
||||
playerdata->collection->addRandomCards(3,setId,RARITY_R,NULL);
|
||||
playerdata->collection->addRandomCards(9, setId,RARITY_U,NULL);
|
||||
playerdata->collection->addRandomCards(48, setId,RARITY_C,NULL);
|
||||
}else{
|
||||
//Booster
|
||||
playerdata->collection->addRandomCards(1, setId,RARITY_R);
|
||||
playerdata->collection->addRandomCards(3, setId,RARITY_U);
|
||||
playerdata->collection->addRandomCards(11, setId,RARITY_C);
|
||||
}
|
||||
int newNbCards = playerdata->collection->totalCards();;
|
||||
for (int i = curNbcards; i < newNbCards ; i++){
|
||||
MTGCardInstance * card = NEW MTGCardInstance(playerdata->collection->_(i), NULL);
|
||||
displayCards[i-curNbcards] = card;
|
||||
display->AddCard(card);
|
||||
}
|
||||
}
|
||||
//Remove(showPriceDialog);
|
||||
showPriceDialog = -1;
|
||||
}else{
|
||||
//error not enough money
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (item->card){
|
||||
int rnd = (rand() % 5);
|
||||
price = price - (rnd * price)/100;
|
||||
pricelist->setPrice(item->card->getMTGId(),price);
|
||||
}
|
||||
showPriceDialog = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ShopItems::safeDeleteDisplay(){
|
||||
if (!display) return;
|
||||
for (int i = 0; i < display->mCount; i++){
|
||||
delete displayCards[i];
|
||||
}
|
||||
SAFE_DELETE(display);
|
||||
}
|
||||
|
||||
void ShopItems::saveAll(){
|
||||
savePriceList();
|
||||
playerdata->save();
|
||||
}
|
||||
|
||||
void ShopItems::savePriceList(){
|
||||
pricelist->save();
|
||||
}
|
||||
|
||||
ShopItems::~ShopItems(){
|
||||
SAFE_DELETE(pricelist);
|
||||
SAFE_DELETE(playerdata);
|
||||
SAFE_DELETE(dialog);
|
||||
safeDeleteDisplay();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/SimpleMenu.h"
|
||||
#include "../include/SimpleMenuItem.h"
|
||||
|
||||
SimpleMenu::SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int y, int width, const char * _title): JGuiController(id, listener){
|
||||
mHeight = 0;
|
||||
mWidth = width;
|
||||
mX = x;
|
||||
mY = y;
|
||||
mFont = font;
|
||||
if (_title){
|
||||
displaytitle = 1;
|
||||
title = _title;
|
||||
mHeight = 20;
|
||||
}else{
|
||||
displaytitle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleMenu::Render(){
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
JRenderer * renderer = JRenderer::GetInstance();
|
||||
renderer->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(70,0,0,0));
|
||||
renderer->FillRoundRect(mX,mY,mWidth,mHeight,10,ARGB(255,17,17,17));
|
||||
renderer->FillRoundRect(mX+2,mY+2,mWidth - 4,mHeight-4,10,ARGB(255,62,62,62));
|
||||
if (displaytitle)
|
||||
mFont->DrawString(title.c_str(), mX+10, mY+10);
|
||||
JGuiController::Render();
|
||||
}
|
||||
|
||||
void SimpleMenu::Add(int id, const char * text){
|
||||
JGuiController::Add(NEW SimpleMenuItem(id, mFont, text, mWidth/2 + mX + 10, mY + 10 + mHeight, (mCount == 0)));
|
||||
mHeight += 20;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/SimpleMenuItem.h"
|
||||
|
||||
|
||||
SimpleMenuItem::SimpleMenuItem(int id, JLBFont *font, const char* text, int x, int y, bool hasFocus): JGuiObject(id), mFont(font), mText(text), mX(x), mY(y)
|
||||
{
|
||||
|
||||
|
||||
mHasFocus = hasFocus;
|
||||
|
||||
mScale = 1.0f;
|
||||
mTargetScale = 1.0f;
|
||||
|
||||
|
||||
|
||||
if (hasFocus)
|
||||
Entering();
|
||||
mFont->SetScale(1.2f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SimpleMenuItem::Render()
|
||||
{
|
||||
|
||||
mFont->SetScale(mScale);
|
||||
mFont->SetColor(ARGB(255,255,255,255));
|
||||
if (mHasFocus)
|
||||
{
|
||||
mFont->SetColor(ARGB(255,255,255,0));
|
||||
}
|
||||
mFont->DrawString(mText, mX, mY, JGETEXT_CENTER);
|
||||
mFont->SetScale(1.0f);
|
||||
}
|
||||
|
||||
void SimpleMenuItem::Update(float dt)
|
||||
{
|
||||
if (mScale < mTargetScale)
|
||||
{
|
||||
mScale += 8.0f*dt;
|
||||
if (mScale > mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
else if (mScale > mTargetScale)
|
||||
{
|
||||
mScale -= 8.0f*dt;
|
||||
if (mScale < mTargetScale)
|
||||
mScale = mTargetScale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SimpleMenuItem::Entering()
|
||||
{
|
||||
|
||||
mHasFocus = true;
|
||||
mTargetScale = 1.2f;
|
||||
}
|
||||
|
||||
|
||||
bool SimpleMenuItem::Leaving(u32 key)
|
||||
{
|
||||
mHasFocus = false;
|
||||
mTargetScale = 1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SimpleMenuItem::ButtonPressed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/Subtypes.h"
|
||||
#include <JGE.h>
|
||||
#include <algorithm>
|
||||
|
||||
Subtypes * Subtypes::subtypesList = NEW Subtypes();
|
||||
|
||||
|
||||
|
||||
Subtypes::Subtypes(){
|
||||
nb_items = 0;
|
||||
offset = 100;
|
||||
}
|
||||
|
||||
int Subtypes::Add(string value){
|
||||
int result = find(value);
|
||||
if (result) return result;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Adding new type: *%s*\n",value.c_str());
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
std::transform( value.begin(), value.end(), value.begin(), ::tolower );
|
||||
values[nb_items] = value;
|
||||
nb_items++;
|
||||
return nb_items + offset - 1;
|
||||
}
|
||||
|
||||
int Subtypes::Add(const char * subtype){
|
||||
string value = subtype;
|
||||
return Add(value);
|
||||
|
||||
}
|
||||
|
||||
int Subtypes::find(string value){
|
||||
std::transform( value.begin(), value.end(), value.begin(), ::tolower );
|
||||
for (int i = 0; i < nb_items; i++){
|
||||
if(values[i].compare(value) == 0){
|
||||
return i + offset;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Subtypes::find(const char * subtype){
|
||||
string value = subtype;
|
||||
return (find(value));
|
||||
|
||||
}
|
||||
@@ -0,0 +1,462 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/TargetChooser.h"
|
||||
|
||||
#include "../include/MTGGameZones.h"
|
||||
#include "../include/GameObserver.h"
|
||||
#include "../include/Subtypes.h"
|
||||
|
||||
|
||||
|
||||
TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInstance * card){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
MTGGameZone * zones[10];
|
||||
int nbzones = 0;
|
||||
int size = s.size();
|
||||
if (size != 0){
|
||||
unsigned int found;
|
||||
found = s.find("player");
|
||||
if (found != string::npos){
|
||||
int maxtargets = 1;
|
||||
unsigned int several = s.find_first_of('s',5);
|
||||
if (several != string::npos) maxtargets = -1;
|
||||
found = s.find("creature");
|
||||
if (found != string::npos){
|
||||
return NEW DamageableTargetChooser(card,maxtargets); //Any Damageable target (player, creature)
|
||||
}else{
|
||||
return NEW PlayerTargetChooser(card,maxtargets); //Any player
|
||||
}
|
||||
}else{
|
||||
string s1;
|
||||
found = s.find("|");
|
||||
if (found != string::npos){
|
||||
string s2;
|
||||
s1 = s.substr(0,found);
|
||||
s2 = s.substr(found+1);
|
||||
while(s2.size()){
|
||||
found = s2.find(",");
|
||||
string zoneName;
|
||||
if (found != string::npos){
|
||||
zoneName = s2.substr(0,found);
|
||||
s2 = s2.substr(found+1);
|
||||
}else{
|
||||
zoneName = s2;
|
||||
s2 = "";
|
||||
}
|
||||
//Graveyards
|
||||
if (zoneName.compare("mygraveyard") == 0){
|
||||
zones[nbzones] = game->currentlyActing()->game->graveyard;
|
||||
}else if(zoneName.compare("opponentgraveyard") == 0){
|
||||
zones[nbzones] = game->currentlyActing()->opponent()->game->graveyard;
|
||||
}else if(zoneName.compare("graveyard") == 0){
|
||||
zones[nbzones] = game->players[0]->game->graveyard;
|
||||
nbzones++;
|
||||
zones[nbzones] = game->players[1]->game->graveyard;
|
||||
}else{
|
||||
|
||||
//inPlay
|
||||
if (zoneName.compare("myinplay") == 0){
|
||||
zones[nbzones] = game->currentlyActing()->game->inPlay;
|
||||
}else if(zoneName.compare("opponentinplay") == 0){
|
||||
zones[nbzones] = game->currentlyActing()->opponent()->game->inPlay;
|
||||
}else if(zoneName.compare("inplay") == 0){
|
||||
zones[nbzones] = game->players[0]->game->inPlay;
|
||||
nbzones++;
|
||||
zones[nbzones] = game->players[1]->game->inPlay;
|
||||
}else{
|
||||
zones[nbzones] = game->currentlyActing()->game->inPlay;
|
||||
}
|
||||
}
|
||||
nbzones++;
|
||||
}
|
||||
}else{
|
||||
s1 = s;
|
||||
nbzones = 2;
|
||||
zones[0]= game->players[0]->game->inPlay;
|
||||
zones[1]= game->players[1]->game->inPlay;
|
||||
}
|
||||
|
||||
TypeTargetChooser * tc = NULL;
|
||||
int maxtargets = 1;
|
||||
|
||||
while(s1.size()){
|
||||
found = s1.find(",");
|
||||
string typeName;
|
||||
if (found != string::npos){
|
||||
typeName = s1.substr(0,found);
|
||||
s1 = s1.substr(found+1);
|
||||
}else{
|
||||
typeName = s1;
|
||||
s1 = "";
|
||||
}
|
||||
//X targets allowed ?
|
||||
if (typeName.at(typeName.length()-1) == 's'){
|
||||
typeName = typeName.substr(0,typeName.length()-1);
|
||||
maxtargets = -1;
|
||||
}
|
||||
if (!tc){
|
||||
if (typeName.compare("*")==0){
|
||||
return NEW TargetZoneChooser(zones, nbzones,card, maxtargets);
|
||||
}else{
|
||||
tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets);
|
||||
}
|
||||
}else{
|
||||
tc->addType(typeName.c_str());
|
||||
tc->maxtargets = maxtargets;
|
||||
}
|
||||
}
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card){
|
||||
int id = card->model->getId();
|
||||
string s = card->spellTargetType;
|
||||
if (card->alias){
|
||||
id = card->alias;
|
||||
//TODO load target as well... ?
|
||||
}
|
||||
TargetChooser * tc = createTargetChooser(s, card);
|
||||
if (tc) return tc;
|
||||
//Any target than cannot be defined automatically is determined by its id
|
||||
switch (id){
|
||||
//Spell
|
||||
case 1196: //CounterSpell
|
||||
case 1224: //Spell blast
|
||||
{
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString ("Counter Spell !\n");
|
||||
#endif
|
||||
return NEW SpellTargetChooser(card);
|
||||
}
|
||||
//Spell Or Permanent
|
||||
case 1282: //ChaosLace
|
||||
case 1152: //DeathLace
|
||||
case 1358: //PureLace
|
||||
case 1227: //ThoughLace
|
||||
case 1257: //Lifelace
|
||||
{
|
||||
return NEW SpellOrPermanentTargetChooser(card);
|
||||
}
|
||||
//Red Spell or Permanent
|
||||
case 1191: //Blue Elemental Blast
|
||||
{
|
||||
return NEW SpellOrPermanentTargetChooser(card,MTG_COLOR_RED);
|
||||
}
|
||||
//Blue Spell or Permanent
|
||||
case 1312: //Red Elemental Blast
|
||||
{
|
||||
return NEW SpellOrPermanentTargetChooser(card,MTG_COLOR_BLUE);
|
||||
}
|
||||
//Damage History
|
||||
case 1344: //Eye for an Eye
|
||||
{
|
||||
return NEW DamageTargetChooser(card,-1,1,RESOLVED_OK);
|
||||
}
|
||||
default:
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets): TargetsList(){
|
||||
forceTargetListReady = 0;
|
||||
source = card;
|
||||
maxtargets = _maxtargets;
|
||||
}
|
||||
|
||||
//Default targetter : every card can be targetted, unless it is protected from the source card
|
||||
int TargetChooser::canTarget(Targetable * target){
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
if (source && card->protectedAgainst(source)) return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int TargetChooser::addTarget(Targetable * target){
|
||||
if (canTarget(target) && TargetsList::addTarget(target)){
|
||||
}
|
||||
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
char buf[4096];
|
||||
sprintf(buf, "Nb targets : %i\n", cursor);
|
||||
OutputDebugString(buf);
|
||||
#endif
|
||||
return targetsReadyCheck();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int TargetChooser::ForceTargetListReady(){
|
||||
int state = targetsReadyCheck() ;
|
||||
if (state == TARGET_OK){
|
||||
forceTargetListReady = 1;
|
||||
}
|
||||
return forceTargetListReady;
|
||||
}
|
||||
|
||||
int TargetChooser::targetsReadyCheck(){
|
||||
if (cursor == 0){
|
||||
return TARGET_NOK;
|
||||
}
|
||||
if (full()){
|
||||
return TARGET_OK_FULL;
|
||||
}
|
||||
if (!ready()){
|
||||
return TARGET_OK_NOT_READY;
|
||||
}
|
||||
return TARGET_OK;
|
||||
}
|
||||
|
||||
int TargetChooser::targetListSet(){
|
||||
int state = targetsReadyCheck();
|
||||
if (state == TARGET_OK_FULL || forceTargetListReady){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Choose anything that has a given list of types
|
||||
**/
|
||||
TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
int id = Subtypes::subtypesList->Add(_type);
|
||||
nbtypes = 0;
|
||||
addType(id);
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
}
|
||||
|
||||
TypeTargetChooser::TypeTargetChooser(const char * _type, MTGGameZone ** _zones, int nbzones, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
int id = Subtypes::subtypesList->Add(_type);
|
||||
nbtypes = 0;
|
||||
addType(id);
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
if (nbzones == 0){
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
}else{
|
||||
init(_zones, nbzones);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeTargetChooser::addType(const char * _type){
|
||||
int id = Subtypes::subtypesList->Add(_type);
|
||||
addType(id);
|
||||
}
|
||||
|
||||
void TypeTargetChooser::addType(int type){
|
||||
types[nbtypes] = type;
|
||||
nbtypes++;
|
||||
}
|
||||
|
||||
int TypeTargetChooser::canTarget(Targetable * target ){
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
if (!TargetZoneChooser::canTarget(card)) return 0;
|
||||
int result = 0;
|
||||
for (int i= 0; i < nbtypes; i++){
|
||||
result += card->hasSubtype(types[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Choose a creature anywhere. This is actually not enough as a zone should be selected
|
||||
**/
|
||||
|
||||
CreatureTargetChooser::CreatureTargetChooser( MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
maxpower= -1;
|
||||
}
|
||||
|
||||
CreatureTargetChooser::CreatureTargetChooser(MTGGameZone ** _zones, int nbzones, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
if (nbzones == 0){
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
}else{
|
||||
init(_zones, nbzones);
|
||||
}
|
||||
maxpower = -1;
|
||||
}
|
||||
|
||||
|
||||
int CreatureTargetChooser::canTarget(Targetable * target){
|
||||
if (!TargetZoneChooser::canTarget(target)) return 0;
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
if (maxpower != -1 && card->power > maxpower) return 0;
|
||||
return card->isACreature();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TargetZoneChooser::TargetZoneChooser(MTGCardInstance * card, int _maxtargets){
|
||||
init(NULL,0);
|
||||
source = card;
|
||||
maxtargets = _maxtargets;
|
||||
}
|
||||
|
||||
TargetZoneChooser::TargetZoneChooser(MTGGameZone ** _zones, int _nbzones,MTGCardInstance * card, int _maxtargets){
|
||||
init(_zones, _nbzones);
|
||||
source = card;
|
||||
maxtargets = _maxtargets;
|
||||
}
|
||||
|
||||
int TargetZoneChooser::init(MTGGameZone ** _zones, int _nbzones){
|
||||
for (int i = 0; i < _nbzones; i++){
|
||||
zones[i] = _zones[i];
|
||||
}
|
||||
nbzones = _nbzones;
|
||||
return nbzones;
|
||||
}
|
||||
|
||||
int TargetZoneChooser::canTarget(Targetable * target){
|
||||
if (!TargetChooser::canTarget(target)) return 0;
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
for (int i = 0; i<nbzones; i++){
|
||||
if (zones[i]->hasCard(card)) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Player Target */
|
||||
int PlayerTargetChooser::canTarget(Targetable * target){
|
||||
if (target->typeAsTarget() == TARGET_PLAYER){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Damageable Target */
|
||||
int DamageableTargetChooser::canTarget(Targetable * target){
|
||||
if (target->typeAsTarget() == TARGET_PLAYER){
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString("Targetting Player !!!\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return CreatureTargetChooser::canTarget(target);
|
||||
}
|
||||
|
||||
|
||||
/*Spell */
|
||||
|
||||
|
||||
|
||||
SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card,int _color, int _maxtargets ):TargetChooser(card, _maxtargets){
|
||||
color = _color;
|
||||
}
|
||||
|
||||
int SpellTargetChooser::canTarget(Targetable * target){
|
||||
MTGCardInstance * card = NULL;
|
||||
if (target->typeAsTarget() == TARGET_STACKACTION){
|
||||
Interruptible * action = (Interruptible *) target;
|
||||
if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){
|
||||
Spell * spell = (Spell *) action;
|
||||
card = spell->source;
|
||||
if (card && (color == -1 || card->hasColor(color))) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*Spell or Permanent */
|
||||
SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
color = _color;
|
||||
}
|
||||
|
||||
int SpellOrPermanentTargetChooser::canTarget(Targetable * target){
|
||||
MTGCardInstance * card = NULL;
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
card = (MTGCardInstance *) target;
|
||||
if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target);
|
||||
}else if (target->typeAsTarget() == TARGET_STACKACTION){
|
||||
Interruptible * action = (Interruptible *) target;
|
||||
if (action->type == ACTION_SPELL && action->state==NOT_RESOLVED){
|
||||
Spell * spell = (Spell *) action;
|
||||
card = spell->source;
|
||||
if (card && (color == -1 || card->hasColor(color))) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Damage */
|
||||
DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, int _state):TargetChooser(card, _maxtargets){
|
||||
color = _color;
|
||||
state = _state;
|
||||
}
|
||||
|
||||
int DamageTargetChooser::canTarget(Targetable * target){
|
||||
MTGCardInstance * card = NULL;
|
||||
if (target->typeAsTarget() == TARGET_STACKACTION){
|
||||
Interruptible * action = (Interruptible *) target;
|
||||
if (action->type == ACTION_DAMAGE && (action->state == state || state == -1)){
|
||||
Damage * damage = (Damage *) action;
|
||||
card = damage->source;
|
||||
if (card && (color == -1 || card->hasColor(color))) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*Damage or Permanent */
|
||||
DamageOrPermanentTargetChooser::DamageOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets):TargetZoneChooser(card, _maxtargets){
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
MTGGameZone * default_zones[] = {game->players[0]->game->inPlay, game->players[1]->game->inPlay};
|
||||
init(default_zones,2);
|
||||
color = _color;
|
||||
}
|
||||
|
||||
int DamageOrPermanentTargetChooser::canTarget(Targetable * target){
|
||||
MTGCardInstance * card = NULL;
|
||||
if (target->typeAsTarget() == TARGET_CARD){
|
||||
card = (MTGCardInstance *) target;
|
||||
if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target);
|
||||
}else if (target->typeAsTarget() == TARGET_STACKACTION){
|
||||
Interruptible * action = (Interruptible *) target;
|
||||
if (action->type == ACTION_DAMAGE){
|
||||
Damage * damage = (Damage *) action;
|
||||
card = damage->source;
|
||||
if (card && (color == -1 || card->hasColor(color))) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/TargetsList.h"
|
||||
#include "../include/Player.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/Damage.h"
|
||||
#include "../include/ActionStack.h"
|
||||
|
||||
TargetsList::TargetsList(){
|
||||
cursor = 0;
|
||||
}
|
||||
|
||||
TargetsList::TargetsList(Targetable * _targets[], int nbtargets){
|
||||
for (int i = 0; i < nbtargets; i++){
|
||||
targets[i] = _targets[i];
|
||||
}
|
||||
cursor = nbtargets;
|
||||
}
|
||||
|
||||
int TargetsList::addTarget(Targetable * target){
|
||||
if (!alreadyHasTarget(target)){
|
||||
targets[cursor] = target;
|
||||
cursor++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int TargetsList::alreadyHasTarget(Targetable * target){
|
||||
for (int i=0; i<cursor; i++){
|
||||
if (targets[i] == target) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TargetsList::removeTarget(Targetable * target){
|
||||
for (int i=0; i<cursor; i++){
|
||||
if (targets[i] == target) {
|
||||
targets[i] = targets[cursor];
|
||||
targets[cursor] = NULL;
|
||||
cursor--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int TargetsList::toggleTarget(Targetable * target){
|
||||
if (alreadyHasTarget(target)){
|
||||
|
||||
return removeTarget(target);
|
||||
}else{
|
||||
|
||||
return addTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Targetable * TargetsList::getNextTarget(Targetable * previous, int type){
|
||||
int found = 0;
|
||||
if (!previous) found = 1;
|
||||
for (int i = 0; i < cursor; i++){
|
||||
if (found && targets[i]->typeAsTarget() == type){
|
||||
return (targets[i]);
|
||||
}
|
||||
if (targets[i] == previous) found = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MTGCardInstance * TargetsList::getNextCardTarget(MTGCardInstance * previous){
|
||||
return ((MTGCardInstance *)getNextTarget(previous, TARGET_CARD));
|
||||
}
|
||||
|
||||
|
||||
Player * TargetsList::getNextPlayerTarget(Player * previous){
|
||||
return ((Player *)getNextTarget(previous, TARGET_PLAYER));
|
||||
}
|
||||
|
||||
|
||||
Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int type){
|
||||
int found = 0;
|
||||
if (!previous) found = 1;
|
||||
for (int i = 0; i < cursor; i++){
|
||||
if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION){
|
||||
Interruptible * action = (Interruptible *) targets[i];
|
||||
if (action->type==type){
|
||||
return action;
|
||||
}
|
||||
}
|
||||
if (targets[i] == previous) found = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Spell * TargetsList::getNextSpellTarget(Spell * previous){
|
||||
Spell * spell = (Spell *) getNextInterruptible(previous, ACTION_SPELL);
|
||||
return spell;
|
||||
}
|
||||
|
||||
//How about DAMAGESTacks ??
|
||||
Damage * TargetsList::getNextDamageTarget(Damage * previous){
|
||||
Damage * damage = (Damage * ) getNextInterruptible(previous, ACTION_DAMAGE);
|
||||
return damage;
|
||||
}
|
||||
|
||||
Damageable * TargetsList::getNextDamageableTarget(Damageable * previous){
|
||||
int found = 0;
|
||||
if (!previous) found = 1;
|
||||
for (int i = 0; i < cursor; i++){
|
||||
|
||||
if (targets[i]->typeAsTarget() == TARGET_PLAYER){
|
||||
if (found){
|
||||
return ((Player *) targets[i]);
|
||||
}else{
|
||||
if ((Player *)targets[i] == previous) found = 1;
|
||||
}
|
||||
}else if(targets[i]->typeAsTarget() == TARGET_CARD){
|
||||
if (found){
|
||||
return ((MTGCardInstance *) targets[i]);
|
||||
}else{
|
||||
if ((MTGCardInstance *)targets[i] == previous) found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
#include "../include/TestSuiteAI.h"
|
||||
#include "../include/debug.h"
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
TestSuiteAI::TestSuiteAI(MTGAllCards* collection, TestSuite * _suite, int playerId):AIPlayer(_suite->buildDeck(collection, playerId),"testsuite"){
|
||||
suite = _suite;
|
||||
timer= 0;
|
||||
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
|
||||
if (mAvatarTex){
|
||||
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
|
||||
}
|
||||
}
|
||||
|
||||
MTGCardInstance * TestSuite::getCardByMTGId(int mtgid){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
for (int i = 0; i < 2; i++){
|
||||
Player * p = g->players[i];
|
||||
MTGGameZone * zones[] = {p->game->library,p->game->hand, p->game->inPlay, p->game->graveyard};
|
||||
for (int j = 0; j < 4; j++){
|
||||
MTGGameZone * zone = zones[j];
|
||||
for (int k = 0; k < zone->nb_cards; k++){
|
||||
MTGCardInstance * card = zone->cards[k];
|
||||
if (!card) OutputDebugString ("wtf ?");
|
||||
if (card->getMTGId() == mtgid) return card;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Interruptible * TestSuite::getActionByMTGId(int mtgid){
|
||||
ActionStack * as= GameObserver::GetInstance()->mLayers->stackLayer();
|
||||
Interruptible * action = NULL;
|
||||
while (action = as->getNext(action,0,0,1)){
|
||||
if (action->source && action->source->getMTGId() == mtgid){
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TestSuiteAI::Act(){
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
g->gameOver = NULL; // Prevent draw rule from losing the game
|
||||
timer++;
|
||||
if (timer < 20) return 1;
|
||||
timer = 0;
|
||||
string action = suite->getNextAction();
|
||||
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){
|
||||
if(action.compare("no") != 0 && action.compare("yes") != 0){
|
||||
g->mLayers->stackLayer()->cancelInterruptOffer();
|
||||
suite->currentAction--;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == ""){
|
||||
//end of game
|
||||
suite->assertGame();
|
||||
g->gameOver = g->players[0];
|
||||
return 1;
|
||||
}
|
||||
if (action.compare("eot")== 0){
|
||||
if (g->getCurrentGamePhase() != MTG_PHASE_CLEANUP) suite->currentAction--;
|
||||
g->userRequestNextGamePhase();
|
||||
}
|
||||
else if (action.compare("next")==0){
|
||||
g->userRequestNextGamePhase();
|
||||
}else if (action.compare("yes")==0){
|
||||
g->mLayers->stackLayer()->setIsInterrupting(this);
|
||||
}else if (action.compare("endinterruption")==0){
|
||||
g->mLayers->stackLayer()->endOfInterruption();
|
||||
}else if(action.compare("no")==0){
|
||||
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this){
|
||||
g->mLayers->stackLayer()->cancelInterruptOffer();
|
||||
}
|
||||
}else{
|
||||
int mtgid = atoi(action.c_str());
|
||||
if (mtgid){
|
||||
MTGCardInstance * card = suite->getCardByMTGId(mtgid);
|
||||
if (card) {
|
||||
g->cardClick(card);
|
||||
}else{
|
||||
Interruptible * action = suite->getActionByMTGId(mtgid);
|
||||
if (action){
|
||||
g->stackObjectClicked(action);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
TestSuiteActions::TestSuiteActions(){
|
||||
nbitems = 0;
|
||||
}
|
||||
|
||||
void TestSuiteActions::add(string s){
|
||||
actions[nbitems] = s;
|
||||
nbitems++;
|
||||
}
|
||||
|
||||
TestSuitePlayerData::TestSuitePlayerData(){
|
||||
life = 20;
|
||||
manapool = NEW ManaCost();
|
||||
}
|
||||
|
||||
TestSuitePlayerData::~TestSuitePlayerData(){
|
||||
SAFE_DELETE(manapool);
|
||||
}
|
||||
|
||||
TestSuitePlayerZone::TestSuitePlayerZone(){
|
||||
nbitems = 0;
|
||||
}
|
||||
|
||||
void TestSuitePlayerZone::add(int cardId){
|
||||
cards[nbitems] = cardId;
|
||||
nbitems++;
|
||||
}
|
||||
|
||||
TestSuiteState::TestSuiteState(){
|
||||
|
||||
}
|
||||
|
||||
void TestSuiteState::parsePlayerState(int playerId, string s){
|
||||
int limiter = s.find(":");
|
||||
string areaS;
|
||||
int area;
|
||||
if (limiter != string::npos){
|
||||
areaS = s.substr(0,limiter);
|
||||
if (areaS.compare("graveyard") == 0){
|
||||
area = 0;
|
||||
}else if(areaS.compare("library") == 0){
|
||||
area = 1;
|
||||
}else if(areaS.compare("hand") == 0){
|
||||
area = 2;
|
||||
}else if(areaS.compare("inplay") == 0 ){
|
||||
area = 3;
|
||||
}else if(areaS.compare("life") == 0){
|
||||
playerData[playerId].life = atoi((s.substr(limiter+1)).c_str());
|
||||
return;
|
||||
}else if(areaS.compare("manapool") == 0){
|
||||
SAFE_DELETE(playerData[playerId].manapool);
|
||||
playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter+1));
|
||||
return;
|
||||
}
|
||||
s = s.substr(limiter+1);
|
||||
while (s.size()){
|
||||
int value;
|
||||
limiter = s.find(",");
|
||||
if (limiter != string::npos){
|
||||
value = atoi(s.substr(0,limiter).c_str());
|
||||
s = s.substr(limiter+1);
|
||||
}else{
|
||||
value = atoi(s.c_str());
|
||||
s = "";
|
||||
}
|
||||
playerData[playerId].zones[area].add(value);
|
||||
}
|
||||
}else{
|
||||
//ERROR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string TestSuite::getNextAction(){
|
||||
if (actions.nbitems && currentAction < actions.nbitems){
|
||||
currentAction++;
|
||||
return actions.actions[currentAction-1];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
MTGPlayerCards * TestSuite::buildDeck(MTGAllCards * collection, int playerId){
|
||||
char buf[4096];
|
||||
int list[100];
|
||||
int nbcards = 0;
|
||||
for (int j = 0; j < 4; j++){
|
||||
for (int k = 0; k < initState.playerData[playerId].zones[j].nbitems; k++){
|
||||
int cardid = initState.playerData[playerId].zones[j].cards[k];
|
||||
list[nbcards] = cardid;
|
||||
nbcards++;
|
||||
}
|
||||
}
|
||||
MTGPlayerCards * deck = NEW MTGPlayerCards(collection, list, nbcards);
|
||||
return deck;
|
||||
}
|
||||
|
||||
void TestSuite::initGame(){
|
||||
//Put the GameObserver in the initial state
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
OutputDebugString("Init Game\n");
|
||||
g->currentGamePhase = initState.phase;
|
||||
for (int i = 0; i < 2; i++){
|
||||
Player * p = g->players[i];
|
||||
p->life = initState.playerData[i].life;
|
||||
p->getManaPool()->copy(initState.playerData[i].manapool);
|
||||
MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay};
|
||||
for (int j = 0; j < 4; j++){
|
||||
MTGGameZone * zone = playerZones[j];
|
||||
for (int k = 0; k < initState.playerData[i].zones[j].nbitems; k++){
|
||||
MTGCardInstance * card = getCardByMTGId(initState.playerData[i].zones[j].cards[k]);
|
||||
if (card && zone != p->game->library){
|
||||
if (zone == p->game->inPlay){
|
||||
p->game->putInZone(card, p->game->library, p->game->hand);
|
||||
Spell * spell = NEW Spell(card);
|
||||
p->game->putInZone(card, p->game->hand, p->game->stack);
|
||||
spell->resolve();
|
||||
card->summoningSickness = 0;
|
||||
delete spell;
|
||||
}else{
|
||||
if (!p->game->library->hasCard(card)){
|
||||
LOG ("ERROR, CARD NOT FOUND IN LIBRARY\n");
|
||||
}
|
||||
p->game->putInZone(card,p->game->library,zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OutputDebugString("Init Game Done !\n");
|
||||
}
|
||||
|
||||
int TestSuite::Log(const char * text){
|
||||
ofstream file ("Res/test/results.txt",ios_base::app);
|
||||
if (file){
|
||||
file << text;
|
||||
file << "\n";
|
||||
file.close();
|
||||
}
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
OutputDebugString(text);
|
||||
OutputDebugString("\n");
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
}
|
||||
int TestSuite::assertGame(){
|
||||
//compare the game state with the results
|
||||
Log("=============================");
|
||||
Log(files[currentfile-1].c_str());
|
||||
char result[4096];
|
||||
int error = 0;
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
if (g->currentGamePhase != endState.phase){
|
||||
sprintf(result, "==phase problem. Expected %i, got %i==",endState.phase, g->currentGamePhase);
|
||||
Log(result);
|
||||
error++;
|
||||
}
|
||||
for (int i = 0; i < 2; i++){
|
||||
Player * p = g->players[i];
|
||||
if (p->life != endState.playerData[i].life){
|
||||
sprintf(result, "==life problem for player %i. Expected %i, got %i==",i,endState.playerData[i].life, p->life);
|
||||
Log(result);
|
||||
error++;
|
||||
}
|
||||
if (! p->getManaPool()->canAfford(endState.playerData[i].manapool)){
|
||||
sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==",endState.playerData[i].manapool->getConvertedCost(),p->getManaPool()->getConvertedCost(),i);
|
||||
Log(result);
|
||||
error++;
|
||||
}
|
||||
if(! endState.playerData[i].manapool->canAfford(p->getManaPool())){
|
||||
sprintf(result, "==Mana problem. Was expecting %i but got %i for player %i==",endState.playerData[i].manapool->getConvertedCost(),p->getManaPool()->getConvertedCost(),i);
|
||||
Log(result);
|
||||
error++;
|
||||
|
||||
}
|
||||
MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay};
|
||||
for (int j = 0; j < 4; j++){
|
||||
MTGGameZone * zone = playerZones[j];
|
||||
if (zone->nb_cards != endState.playerData[i].zones[j].nbitems){
|
||||
Log("==Card number not the same==");
|
||||
error++;
|
||||
return 0;
|
||||
}
|
||||
for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++){
|
||||
int cardid = endState.playerData[i].zones[j].cards[k];
|
||||
int realcardid = zone->cards[k]->getMTGId();
|
||||
if ( realcardid!= cardid){
|
||||
sprintf(result, "==Card ID not the same. Expected %i, got %i==", cardid, realcardid);
|
||||
Log(result);
|
||||
error++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error) return 0;
|
||||
Log("==Test Succesful !==");
|
||||
return 1;
|
||||
}
|
||||
|
||||
TestSuite::TestSuite(const char * filename){
|
||||
std::ifstream file(filename);
|
||||
std::string s;
|
||||
nbfiles = 0;
|
||||
currentfile = 0;
|
||||
int comment = 0;
|
||||
if(file){
|
||||
while(std::getline(file,s)){
|
||||
if (s[0] == '/' && s[1] == '*') comment = 1;
|
||||
if (s[0] && s[0] != '#' && !comment){
|
||||
files[nbfiles] = s;
|
||||
nbfiles++;
|
||||
}
|
||||
if (s[0] == '*' && s[1] == '/') comment = 0;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
ofstream file2 ("Res/test/results.txt");
|
||||
if (file2){
|
||||
file2 << "\n";
|
||||
file2.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int TestSuite::loadNext(){
|
||||
if (!nbfiles) return 0;
|
||||
if (currentfile >= nbfiles) return 0;
|
||||
load(files[currentfile].c_str());
|
||||
currentfile++;
|
||||
return currentfile;
|
||||
}
|
||||
|
||||
//TODO PArses a string and gives phase numer
|
||||
int TestSuite::phaseStrToInt(string s){
|
||||
if (s.compare("untap") == 0) return MTG_PHASE_UNTAP;
|
||||
if (s.compare("upkeep") == 0)return MTG_PHASE_UPKEEP;
|
||||
if (s.compare("draw") == 0)return MTG_PHASE_DRAW;
|
||||
if (s.compare("firstmain") == 0)return MTG_PHASE_FIRSTMAIN;
|
||||
if (s.compare("combatbegin") == 0)return MTG_PHASE_COMBATBEGIN;
|
||||
if (s.compare("combatattackers") == 0)return MTG_PHASE_COMBATATTACKERS;
|
||||
if (s.compare("combatblockers") == 0)return MTG_PHASE_COMBATBLOCKERS;
|
||||
if (s.compare("combatdamage") == 0)return MTG_PHASE_COMBATDAMAGE;
|
||||
if (s.compare("combatend") == 0)return MTG_PHASE_COMBATEND;
|
||||
if (s.compare("secondmain") == 0)return MTG_PHASE_SECONDMAIN;
|
||||
if (s.compare("endofturn") == 0)return MTG_PHASE_ENDOFTURN;
|
||||
if (s.compare("cleanup") == 0)return MTG_PHASE_CLEANUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void TestSuiteActions::cleanup(){
|
||||
nbitems = 0;
|
||||
}
|
||||
|
||||
void TestSuitePlayerZone::cleanup(){
|
||||
nbitems = 0;
|
||||
}
|
||||
|
||||
void TestSuitePlayerData::cleanup(){
|
||||
if (manapool) delete manapool;
|
||||
manapool = NULL;
|
||||
manapool = NEW ManaCost();
|
||||
for (int i = 0; i < 5; i++){
|
||||
zones[i].cleanup();
|
||||
}
|
||||
life=20;
|
||||
}
|
||||
|
||||
void TestSuiteState::cleanup(){
|
||||
for (int i = 0; i < 2; i++){
|
||||
playerData[i].cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void TestSuite::cleanup(){
|
||||
currentAction = 0;
|
||||
initState.cleanup();
|
||||
endState.cleanup();
|
||||
actions.cleanup();
|
||||
}
|
||||
|
||||
void TestSuite::load(const char * _filename){
|
||||
char filename[4096];
|
||||
sprintf(filename, "Res/test/%s", _filename);
|
||||
std::ifstream file(filename);
|
||||
std::string s;
|
||||
|
||||
int state = -1;
|
||||
|
||||
if(file){
|
||||
cleanup();
|
||||
while(std::getline(file,s)){
|
||||
std::transform( s.begin(), s.end(), s.begin(),::tolower );
|
||||
switch(state){
|
||||
case -1:
|
||||
if (s.compare("[init]") == 0) state++;
|
||||
break;
|
||||
case 0:
|
||||
if (s.compare("[player1]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
initState.phase = phaseStrToInt(s);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (s.compare("[player2]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
initState.parsePlayerState(0, s);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (s.compare("[do]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
initState.parsePlayerState(1, s);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (s.compare("[assert]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
actions.add(s);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (s.compare("[player1]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
endState.phase = phaseStrToInt(s);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (s.compare("[player2]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
endState.parsePlayerState(0, s);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (s.compare("[end]") == 0){
|
||||
state++;
|
||||
}else{
|
||||
endState.parsePlayerState(1, s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}else{
|
||||
//TODO Error management
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/TexturesCache.h"
|
||||
|
||||
TexturesCache::TexturesCache(){
|
||||
nb_textures = 0;
|
||||
totalsize = 0;
|
||||
delete_previous = 0;
|
||||
lastTime = 0;
|
||||
for (int i=0; i<MAX_CACHE_OBJECTS;i++){
|
||||
cache[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TexturesCache::~TexturesCache(){
|
||||
LOG("==Destroying TexturesCache==");
|
||||
for (int i = 0; i < nb_textures; i++){
|
||||
delete cache[i];
|
||||
}
|
||||
LOG("==Destroying TexturesCache Successful==");
|
||||
}
|
||||
|
||||
int TexturesCache::isInCache(MTGCard * card, int type){
|
||||
int cache_id = getCacheById(card->getId(), type);
|
||||
if (cache_id == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TexturesCache::getCacheById(int id, int type){
|
||||
int i;
|
||||
for (i=0; i<nb_textures;i++){
|
||||
if (cache[i]->type == type && cache[i]->getId() == id){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int TexturesCache::getOldestQuad(){
|
||||
int oldest = -1;
|
||||
int result = -1;
|
||||
for (int i= 0; i < nb_textures; i++){
|
||||
if (oldest == -1 || oldest > cache[i]->lastTime){
|
||||
oldest = cache[i]->lastTime;
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TexturesCache::removeQuad(int id){
|
||||
totalsize -= cache[id]->nbpixels;
|
||||
delete cache[id];
|
||||
cache[id] = cache[nb_textures - 1];
|
||||
cache[nb_textures - 1] = NULL;
|
||||
nb_textures--;
|
||||
}
|
||||
|
||||
int TexturesCache::cleanup(){
|
||||
while (nb_textures >= MAX_CACHE_OBJECTS - 1 || totalsize > CACHE_SIZE_PIXELS){
|
||||
int i = getOldestQuad();
|
||||
if (i == -1) return 0;
|
||||
removeQuad(i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
JQuad * TexturesCache::getQuad(MTGCard * card, int type){
|
||||
int cache_id = getCacheById(card->getId(), type);
|
||||
if (cache_id == -1){
|
||||
fprintf(stderr, "not found %d\n", card->getId());
|
||||
//Not found in the cache, we have to load the file and put it in the cache
|
||||
if (cleanup()){
|
||||
cache_id = nb_textures;
|
||||
cache[cache_id] = NEW CardTexture(card, type);
|
||||
totalsize+= cache[cache_id]->nbpixels;
|
||||
nb_textures++;
|
||||
}
|
||||
}
|
||||
cache[cache_id]->lastTime = lastTime++;
|
||||
return cache[cache_id]->getQuad();
|
||||
}
|
||||
|
||||
int CardTexture::getId(){
|
||||
return mtgid;
|
||||
}
|
||||
|
||||
CardTexture::CardTexture(MTGCard * card, int _type): type(_type){
|
||||
LOG("==Creating CardTexture Object");
|
||||
char filename[100];
|
||||
quad = NULL;
|
||||
nbpixels = 0;
|
||||
lastTime = 0;
|
||||
if (type == CACHE_THUMB){
|
||||
sprintf(filename, "sets/%s/thumbnails/%s", card->getSetName(), card->getImageName());
|
||||
}else{
|
||||
sprintf(filename, "sets/%s/%s", card->getSetName(), card->getImageName());
|
||||
}
|
||||
|
||||
tex = JRenderer::GetInstance()->LoadTexture(filename, false);
|
||||
if (tex){
|
||||
quad = NEW JQuad(tex, 0.0f, 0.0f, tex->mWidth, tex->mHeight);
|
||||
nbpixels = tex->mTexHeight * tex->mTexWidth;
|
||||
}
|
||||
mtgid = card->getId();
|
||||
LOG("CardTexture Object Creation succesful");
|
||||
}
|
||||
|
||||
JQuad * CardTexture::getQuad(){
|
||||
return quad;
|
||||
}
|
||||
|
||||
CardTexture::~CardTexture(){
|
||||
LOG("==Deleting CardTexture Object");
|
||||
SAFE_DELETE(quad);
|
||||
SAFE_DELETE(tex);
|
||||
LOG("CardTexture Object deletion Succesful");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "../include/debug.h"
|
||||
#include "../include/utils.h"
|
||||
|
||||
|
||||
int lowercase(string sBuffer) {
|
||||
std::transform( sBuffer.begin(), sBuffer.end(), sBuffer.begin(),
|
||||
::tolower );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int substr_copy(char *source, char *target, int start, int len){
|
||||
int i=0;
|
||||
int not_over = 1;
|
||||
while (not_over){
|
||||
if (source[i+start] == 0 || i == len-1){
|
||||
not_over = 0;
|
||||
}
|
||||
target[i] = source[i + start];
|
||||
i++;
|
||||
if (i == len){
|
||||
target[i] = 0;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int append_str(char * s1, char * s2, char * target){
|
||||
int len = substr_copy(s1,target, 0,0);
|
||||
substr_copy(s2,target+len-1,0,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int filesize(const char * filename){
|
||||
int file_size = 0;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
FILE * file = fopen(filename, "rb");
|
||||
if (file != NULL)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
file_size = ftell(file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
#else
|
||||
int file = sceIoOpen(filename,PSP_O_RDONLY, 0777);
|
||||
if (file > 0){
|
||||
file_size = sceIoLseek(file, 0, PSP_SEEK_END);
|
||||
sceIoClose(file);
|
||||
}
|
||||
|
||||
#endif
|
||||
return file_size;
|
||||
}
|
||||
|
||||
int read_file (const char * filename, char * buffer, int file_size){
|
||||
int a = 0;
|
||||
#if defined (WIN32) || defined (LINUX)
|
||||
FILE * file = fopen(filename, "rb");
|
||||
a = fread(buffer, 1, file_size, file);
|
||||
fclose(file);
|
||||
#else
|
||||
int file = sceIoOpen(filename,PSP_O_RDONLY, 0777);
|
||||
|
||||
a = sceIoRead(file, buffer, file_size);
|
||||
sceIoClose(file);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "The first string in the file is %d characters long.\n", strlen(&buffer[0]) );
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
int readline (char * in_buffer, char * out_buffer, int cursor){
|
||||
char a;
|
||||
int found = 0;
|
||||
int i = 0;
|
||||
|
||||
//int read_ok = 0;
|
||||
while (found == 0){
|
||||
a = in_buffer[cursor];
|
||||
cursor++;
|
||||
if (a == '\r'){
|
||||
a = in_buffer[cursor];
|
||||
cursor ++;
|
||||
}
|
||||
if (a == 0){
|
||||
found = 1;
|
||||
cursor = 0;
|
||||
}else{
|
||||
if(a == '\n' || i==(BUFSIZE - 1)){
|
||||
found = 1;
|
||||
out_buffer[i] = 0;
|
||||
|
||||
if (a != '\n'){
|
||||
int endofline = 0;
|
||||
while (!endofline){
|
||||
//int read;
|
||||
a = in_buffer[cursor];
|
||||
|
||||
cursor++;
|
||||
if (a == 0 || a=='\n'){
|
||||
endofline = 1;
|
||||
fprintf(stderr, "buffer overflow in readline %s\n", out_buffer);
|
||||
}
|
||||
if (a == 0 ){
|
||||
cursor = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
out_buffer[i] = a;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
out_buffer[i] = 0;
|
||||
return(cursor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int readfile_to_ints(const char * filename, int * out_buffer){
|
||||
std::ifstream fichier(filename);
|
||||
std::string s;
|
||||
unsigned int count = 0;
|
||||
if(fichier){
|
||||
while(std::getline(fichier,s)){
|
||||
int value = atoi(s.c_str());
|
||||
if (value){
|
||||
out_buffer[count] = value;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
fichier.close();
|
||||
return count;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user