- fix issue 392 (broken tests)
- Fix a bunch of memory leaks (guys please be careful!)
- Added Logging facility in JGE
- HBL Compatibility (cleaned up some code with MP3 in JGE)
- Added "winGame" ability. Currently used mostly by the story mode, but some cards could probably need it too
- Improved story mode and uncommented it from the source.
-- The current campaign is of course very basic, anybody who wants to improve it or create other ones feel free to do so
-- TODO (short term): save progress, rewards system, improve tutorial campaign
-- I'll talk a bit more about this on the forums/email after a night of sleep
This commit is contained in:
wagic.the.homebrew@gmail.com
2010-04-26 14:27:34 +00:00
parent d311f88f93
commit a3cbbedd3c
30 changed files with 468 additions and 210 deletions

View File

@@ -542,6 +542,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\JLogger.cpp"
>
</File>
<File
RelativePath=".\src\JMD2Model.cpp"
>
@@ -757,6 +761,10 @@
RelativePath="include\JLBFont.h"
>
</File>
<File
RelativePath=".\include\JLogger.h"
>
</File>
<File
RelativePath=".\include\JMD2Model.h"
>

View File

@@ -5,6 +5,7 @@ endif
GENERIC_OBJS = src/JApp.o src/JGBKFont.o \
src/JGE.o src/JGui.o src/JLBFont.o \
src/JLogger.o \
src/JGameObject.o src/JSpline.o src/JAnimator.o \
src/JResourceManager.o src/JFileSystem.o \
src/JNetwork.o \

View File

@@ -23,7 +23,6 @@
#define DEBUG_PRINT
//#define _MP3_ENABLED_
#if defined(WIN32)
#include <windows.h>
@@ -62,9 +61,6 @@ bool JGEToggleFullscreen();
#endif
//#include "JGEInit.h"
//#include "JTypes.h"
#include "Vector2D.h"

View File

@@ -33,6 +33,7 @@ protected:
int m_lastDecoded;
int m_playTime;
int GetID3TagSize(char *fname);
static bool init_done;
public:
int m_paused;
int m_channel;

View File

@@ -8,14 +8,17 @@
#include "../include/JAudio.h"
#include "../include/JFileSystem.h"
#include "../include/JMP3.h"
#include "../include/JLogger.h"
JMP3* JMP3::mInstance = NULL;
bool JMP3::init_done = false;
void JMP3::init() {
loadModules();
if (!init_done) {
init_done = loadModules();
}
}
JMP3::JMP3() :
@@ -27,6 +30,7 @@ JMP3::~JMP3() {
}
bool JMP3::loadModules() {
JLOG("loading Audio modules");
int loadAvCodec = sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC);
if (loadAvCodec < 0) {
return false;
@@ -36,11 +40,16 @@ bool JMP3::loadModules() {
if (loadMp3 < 0) {
return false;
}
JLOG("Audio modules loaded");
return true;
}
bool JMP3::fillBuffers() {
JLOG("Start JMP3::fillBuffers");
if (!init_done) {
JLOG("JMP3::fillBuffers called but init_done is false!");
return false;
}
SceUChar8* dest;
SceInt32 length;
SceInt32 pos;
@@ -72,6 +81,7 @@ bool JMP3::fillBuffers() {
if (ret < 0)
return false;
JLOG("End JMP3::fillBuffers");
return true;
}
int JMP3::GetID3TagSize(char *fname)
@@ -105,6 +115,11 @@ int JMP3::GetID3TagSize(char *fname)
}
bool JMP3::load(const std::string& filename, int inBufferSize, int outBufferSize) {
JLOG("Start JMP3::load");
if (!init_done) {
JLOG("JMP3::load called but init_done is false!");
return false;
}
m_inBufferSize = inBufferSize;
//m_inBuffer = new char[m_inBufferSize];
//if (!m_inBuffer)
@@ -166,10 +181,16 @@ bool JMP3::load(const std::string& filename, int inBufferSize, int outBufferSize
m_numChannels = sceMp3GetMp3ChannelNum(m_mp3Handle);
m_samplingRate = sceMp3GetSamplingRate(m_mp3Handle);
JLOG("End JMP3::load");
return true;
}
bool JMP3::unload() {
JLOG("Start JMP3::unload");
if (!init_done) {
JLOG("JMP3::unload called but init_done is false!");
return false;
}
if (m_channel >= 0)
sceAudioSRCChRelease();
@@ -182,11 +203,14 @@ bool JMP3::unload() {
//delete[] m_inBuffer;
//delete[] m_outBuffer;
JLOG("End JMP3::unload");
return true;
}
bool JMP3::update() {
if (!init_done) {
return false;
}
int retry = 8;//FIXME:magic number
JMP3_update_start:
@@ -238,7 +262,6 @@ bool JMP3::update() {
}
}
return true;
}
@@ -251,8 +274,14 @@ bool JMP3::pause() {
}
bool JMP3::setLoop(bool loop) {
JLOG("Start JMP3::setLoop");
if (!init_done) {
JLOG("JMP3::setLoop called but init_done is false!");
return false;
}
sceMp3SetLoopNum(m_mp3Handle, (loop == true) ? -1 : 0);
return (m_loop = loop);
JLOG("End JMP3::setLoop");
}
int JMP3::setVolume(int volume) {

View File

@@ -20,6 +20,7 @@
#include "../../JGE/include/JApp.h"
#include "../../JGE/include/JGameLauncher.h"
#include "../../JGE/include/JRenderer.h"
#include "../../JGE/include/JLogger.h"
#ifndef JGEApp_Title
@@ -360,8 +361,10 @@ void Run()
// The main loop
int main()
{
JLOG("SetupCallbacks()");
SetupCallbacks();
#ifdef DEVHOOK
JLOG("initExceptionHandler()");
initExceptionHandler();
#endif
g_engine = NULL;
@@ -372,12 +375,16 @@ int main()
if ((flags&JINIT_FLAG_ENABLE3D) != 0)
JRenderer::Set3DFlag(true);
JLOG("sceRtcGetTickResolution()");
gTickFrequency = sceRtcGetTickResolution();
JLOG("JGE::GetInstance()");
g_engine = JGE::GetInstance();
JLOG("Create Game");
game = launcher->GetGameApp();
game->Create();
JLOG("Run Game");
g_engine->SetApp(game);
g_engine->Run();

View File

@@ -1,4 +1,4 @@
OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardPrimitive.o objs/CardSelector.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckMetaData.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateAwards.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GameStateTransitions.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGPack.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/Rules.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/SimplePad.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o
OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardPrimitive.o objs/CardSelector.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DeckDataWrapper.o objs/DeckMetaData.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateAwards.o objs/GameStateDeckViewer.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GameStateStory.o objs/GameStateTransitions.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGPack.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/Rules.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/SimplePad.o objs/StoryFlow.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o
DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS))
RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache)

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,7 @@
[INIT]
mode=mtg
[PLAYER1]
inplay:white knight
auto=@tapped(creature):wingame controller
auto=lord(*) haste
auto=@next secondmain:wingame opponent

View File

@@ -0,0 +1,7 @@
[INIT]
mode=mtg
[PLAYER1]
inplay:plains,plains
hand:white knight
auto=@movedTo(creature|myinplay):wingame controller
auto=@next combatbegins:wingame opponent

View File

@@ -0,0 +1,7 @@
[INIT]
mode=mtg
[PLAYER1]
inplay:plains,forest,mountain,island,swamp
hand:grizzly bears
auto=@movedTo(creature|myinplay):wingame controller
auto=@next combatbegins:wingame opponent

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" ?>
<page id="start">
<type>dialog</type>
<text align="center">WELCOME YOUNG ADVENTURER...</text>
<img y="15">_gfx/shopkeeper.jpg</img>
<text y="115">So you want to become a sorcerer?</text>
<text y="130">You've come to the right place. I'm myself just</text>
<text y="145">a humble retailer, but I've met a lot of adventurers like you</text>
<text y="160">in my life, enough to understand the basics of their craft...</text>
<answer goto="tap_mana_intro">Interested?</answer>
</page>
<page id="tap_mana_intro">
<type>dialog</type>
<text align="center">TAPPING LANDS FOR MANA</text>
<text y="15">In your quests you will have to fight against other wizards.</text>
<text y="30">You will only have your brain and your spells to help you.</text>
<text y="45">The basic Energy to cast your spells in Wagic is called mana.</text>
<text y="60">The most frequent sources of Mana are called "Lands".</text>
<text y="90">For a land to produce mana,</text>
<text y="105">you just have to click on it with the action button (CIRCLE by default)</text>
<answer goto="tap_mana">Go ahead and tap some mana!</answer>
</page>
<page id="tap_mana">
<type>duel</type>
<onwin>tap_mana_ok</onwin>
<onlose>tap_mana_try_again</onlose>
</page>
<page id="tap_mana_try_again">
<type>dialog</type>
<text align="center">HMMM...</text>
<text y="15">It seems you didn't get that right</text>
<text y="30">Simply navigate (with the D-Pad) to the land that appears on your screen,</text>
<text y="45">then click on the action button (CIRCLE by default)</text>
<answer goto="tap_mana">Let's try again!</answer>
</page>
<page id="tap_mana_ok">
<type>dialog</type>
<text align="center">WELL DONE...NOW LET'S CAST A SPELL</text>
<text y="15">That was too easy for you!</text>
<text y="30">Now let's see if you can cast a spell...</text>
<text y="45">Spells have a cost represented by mana symbols on the top right corner</text>
<text y="60">of the card. For example, 2 white mana icons on the top right of the card</text>
<text y="75">means that you have to produce 2 white manas (by activating 2 plains)</text>
<text y="90">in order to put it into play.</text>
<answer goto="cast_spell_1">Try to produce 2 white mana and put a white knight in play</answer>
</page>
<page id="cast_spell_1">
<type>duel</type>
<onwin>cast_spell_1_ok</onwin>
<onlose>cast_spell_1_try_again</onlose>
</page>
<page id="cast_spell_1_try_again">
<type>dialog</type>
<text align="center">HMMM...</text>
<text y="15">It seems you didn't get that right</text>
<text y="30">Simply navigate (with the D-Pad) to the lands that appear on your screen,</text>
<text y="45">then click on the action button (CIRCLE by default) on each of them to produce 2 white mana.</text>
<text y="60">Once this is done, navigate to the White Knight in your hand and click (CIRCLE by default) on it.</text>
<text y="75">Depending on your configuration, you might need to display your hand (RTRIGGER by default)</text>
<answer goto="cast_spell_1">Let's try again!</answer>
</page>
<page id="cast_spell_1_ok">
<type>dialog</type>
<text align="center">PERFECT...BUT THERE'S MORE TO IT</text>
<text y="15">You did great, young adventurer!</text>
<text y="30">But you will see that some spells have slighlty different costs.</text>
<text y="45">Sometimes the cost contains a number with no mana color. It means you can</text>
<text y="60">pay with mana of whatever color you want.</text>
<text y="75">for example a card which cost has a number "1" and a green icon</text>
<text y="90">needs you to pay 1 green mana + a mana of any color if you want to play it.</text>
<answer goto="cast_spell_2">Try to put a grizzly bear card in play.</answer>
</page>
<page id="cast_spell_2">
<type>duel</type>
<onwin>cast_spell_2_ok</onwin>
<onlose>cast_spell_2_try_again</onlose>
</page>
<page id="cast_spell_2_try_again">
<type>dialog</type>
<text align="center">HMMM...</text>
<text y="15">It seems you didn't get that right</text>
<text y="30">Simply navigate (with the D-Pad) to the lands that appear on your screen,</text>
<text y="45">then click on the action button (CIRCLE by default) on some of them to produce some mana.</text>
<text y="60">Remember, you need 1 green mana and one other mana of any color.</text>
<text y="75">Once this is done, navigate to the Grizzly Bears in your hand and click (CIRCLE by default) on it.</text>
<answer goto="cast_spell_2">Let's try again!</answer>
</page>
<page id="cast_spell_2_ok">
<type>dialog</type>
<text align="center">GREAT. NOW LET'S TALK ABOUT PHASES</text>
<text y="15">Once you put them into play, you will want your creatures to attack your opponent.</text>
<text y="30">After all, they are here to help you defeat other sorcerers!</text>
<text y="45">Your creatures can't attack anytime they want, however,</text>
<text y="60">they must wait for the combat phase of your turn.</text>
<text y="75">Your turn is divided into several phases. You can go through the phases by</text>
<text y="90">clicking on LTRIGGER by default. The name of the current phase is displayed on the</text>
<text y="105">top right corner of the screen.</text>
<answer goto="attack">Go to the "Attackers" phase, then click on your White Knight to attack.</answer>
</page>
<page id="attack">
<type>duel</type>
<onwin>attack_ok</onwin>
<onlose>attack_try_again</onlose>
</page>
<page id="attack_try_again">
<type>dialog</type>
<text align="center">HMMM...</text>
<text y="15">It seems you didn't get that right</text>
<text y="30">Go to the "Attackers" phase by clicking on LTRIGGER several times,</text>
<text y="45">then click on your White Knight (with CIRCLE by default) to attack your opponent.</text>
<answer goto="attack">Let's try again!</answer>
</page>
<page id="attack_ok">
<type>dialog</type>
<text align="center">GOOD!</text>
<text y="15">Let me tell you a bit more about phases.</text>
<text y="30">Your turn is divided into several phases. The actions you can perform</text>
<text y="45">Depend on the phase you're in. For now, let's say that you can:</text>
<text y="60">- Play creatures during the "main phase 1" and the "main phase 2" phases of your turn.</text>
<text y="75">- Attack with your creatures during the "Attackers" phase of your turn.</text>
<text y="90">- Block your opponent's attacking creatures during the "blockers" phase of his turn.</text>
<text y="120">There are lots of other phases but we'll discuss them later</text>
<answer goto="End">Continue</answer>
</page>
<page id="End">
<type>End</type>
<text align="center">CONGRATULATIONS!</text>
<text y="15">This is the end of this tutorial,</text>
<text y="30">now time for you to fight some real ennemies!</text>
<text y="60">Click on the action button to go back to the main menu</text>
</page>

View File

@@ -0,0 +1,6 @@
[INIT]
mode=mtg
[PLAYER1]
inplay:forest
auto=@tapped(land|myinplay):wingame controller
auto=@next combatbegins:wingame opponent

View File

@@ -1,21 +0,0 @@
#NAME:Magnivore
#DESC:Do not underestimate
#DESC:this... thing... because
#DESC:it happens to be blind.
#DESC:For if you do, it will
#DESC:be your last mistake!
Hymn to Tourach (FEM) * 4 #
Magnivore (ODY) * 4 #
Stone Rain (CHK) * 4 #
Mountain (RAV) * 4 #
Swamp (RAV) * 4 #
Swamp (TSP) * 4 #
Mountain (TSP) * 4 #
Damnation (PLC) * 4 #
Demolish (10E) * 4 #
Mountain (LRW) * 4 #
Swamp (LRW) * 4 #
Blightning (ALA) * 4 #
Megrim (M10) * 4 #
Sign in Blood (M10) * 4 #
Pyroclasm (M10) * 4 #

View File

@@ -1,9 +0,0 @@
[INIT]
mode=mtg
[PLAYERS]
life:4
auto=shuffle
auto=draw:7
auto=@each my draw:draw:1
[PLAYER2]
library:forest,forest,forest,mountain,mountain,plains,raging goblin,goblin king

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" ?>
<page id="1">
<type>dialog</type>
<text>This is a test Story, what do you want to do?</text>
<answer goto="2">Go left</answer>
<answer goto="3">Go right</answer>
</page>
<page id="2">
<type>dialog</type>
<text>You found the Grail</text>
<answer goto="duel1">click to continue</answer>
</page>
<page id="3">
<type>dialog</type>
<text>You found the Arch of Noah</text>
<answer goto="duel1">click to continue</answer>
</page>
<page id="duel1">
<type>duel</type>
<onwin>End</onwin>
<onlose>1</onlose>
</page>
<page id="End">
<type>End</type>
<text>The End</text>
</page>

View File

@@ -400,7 +400,9 @@ class GenericActivatedAbility:public ActivatedAbility, public NestedAbility{
int resolve(){
counters++;
source->X = abilityCost->Diff(cost)->hasX();
ManaCost * diff = abilityCost->Diff(cost);
source->X = diff->hasX();
SAFE_DELETE(diff);
SAFE_DELETE(abilityCost);
ability->target = target; //may have been updated...
if (ability) return ability->resolve();
@@ -630,6 +632,35 @@ class AALifer:public ActivatedAbilityTP{
};
/*Player Wins Game*/
class AAWinGame:public ActivatedAbilityTP{
public:
AAWinGame(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who){
}
int resolve(){
Damageable * _target = (Damageable *) getTarget();
if (_target){
if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
_target = ((MTGCardInstance *)_target)->controller();
}
game->gameOver = ((Player *)_target)->opponent();
}
return 1;
}
const char * getMenuText(){
return "Win Game";
}
AAWinGame * clone() const{
AAWinGame * a = NEW AAWinGame(*this);
a->isClone = 1;
return a;
}
};
class ATokenCreator:public ActivatedAbility{
@@ -1968,10 +1999,10 @@ class AThisForEach:public MTGAbility, public NestedAbility{
int matches;
matches = td->match(source);
if (matches > 0) {
if (abilities.size() > matches){
if ((int)(abilities.size()) > matches){
removeAbilityFromGame();
}
for (int i = 0; i < matches - abilities.size(); i++) {
for (int i = 0; i < matches - (int)(abilities.size()); i++) {
addAbilityToGame();
}
}
@@ -2988,53 +3019,6 @@ class ALivingArtifact:public MTGAbility{
}
};
//Lord of the Pit
class ALordOfThePit: public TargetAbility{
public:
int paidThisTurn;
ALordOfThePit(int _id, MTGCardInstance * source):TargetAbility(_id, source, NEW CreatureTargetChooser(),0,1,0){
paidThisTurn = 1;
}
void Update(float dt){
if (newPhase != currentPhase && source->controller() == game->currentPlayer){
if (newPhase == Constants::MTG_PHASE_UNTAP){
paidThisTurn = 0;
}else if( newPhase == Constants::MTG_PHASE_UPKEEP + 1 && !paidThisTurn){
game->mLayers->stackLayer()->addDamage(source,source->controller(), 7);
}
}
TargetAbility::Update(dt);
}
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0;
return TargetAbility::isReactingToClick(card,mana);
}
int resolve(){
MTGCardInstance * card = tc->getNextCardTarget();
if (card && card != source && card->controller() == source->controller()){
card->controller()->game->putInGraveyard(card);
paidThisTurn = 1;
return 1;
}
return 0;
}
virtual ostream& toString(ostream& out) const
{
out << "ALordOfThePit ::: paidThisTurn : " << paidThisTurn
<< " (";
return TargetAbility::toString(out) << ")";
}
ALordOfThePit * clone() const{
ALordOfThePit * a = NEW ALordOfThePit(*this);
a->isClone = 1;
return a;
}
};
//1143 Animate Dead
class AAnimateDead:public MTGAbility{
public:
@@ -3577,48 +3561,6 @@ class AFireball:public InstantAbility{
}
};
//1245 ForceOfNature
class AForceOfNature:public ActivatedAbility{
public:
int dealDamageThisTurn;
AForceOfNature(int _id, MTGCardInstance * card):ActivatedAbility(_id,card, NEW ManaCost(),1,0){
dealDamageThisTurn = 0;
cost->add(Constants::MTG_COLOR_GREEN,4);
}
void Update(float dt){
if (newPhase !=currentPhase){
if (newPhase == Constants::MTG_PHASE_UNTAP){
dealDamageThisTurn = 1;
}else if (newPhase == Constants::MTG_PHASE_DRAW && dealDamageThisTurn && game->currentPlayer==source->controller() ){
game->mLayers->stackLayer()->addDamage(source,source->controller(),8);
}
}
ActivatedAbility::Update(dt);
}
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL){
return (dealDamageThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card,mana));
}
int resolve(){
dealDamageThisTurn = 0;
return 1;
}
virtual ostream& toString(ostream& out) const
{
out << "AForceOfNature ::: dealDamageThisTurn : " << dealDamageThisTurn
<< " (";
return ActivatedAbility::toString(out) << ")";
}
AForceOfNature * clone() const{
AForceOfNature * a = NEW AForceOfNature(*this);
a->isClone = 1;
return a;
}
};
//1351 Island Sanctuary
class AIslandSanctuary:public MTGAbility{

View File

@@ -35,12 +35,14 @@
#define PLAYER_TYPE_HUMAN 1
#define PLAYER_TYPE_TESTSUITE 2
#define GAME_TYPE_CLASSIC 0
#define GAME_TYPE_MOMIR 1
#define GAME_TYPE_RANDOM1 2
#define GAME_TYPE_RANDOM2 3
#define GAME_TYPE_STORY 4
enum
{
GAME_TYPE_CLASSIC,
GAME_TYPE_MOMIR,
GAME_TYPE_RANDOM1,
GAME_TYPE_RANDOM2,
GAME_TYPE_STORY
};
class MTGAllCards;
class TransitionBase;

View File

@@ -1,6 +1,9 @@
#ifndef _LOGGER_H
#define _LOGGER_H_
//TODO Remove this and use the jge logging facility (same system)
//#define DOLOG
#ifdef DOLOG
#define LOG(x) Logger::Log(x);
#else

View File

@@ -10,12 +10,39 @@ using namespace std;
class GameObserver;
#define CAMPAIGNS_FOLDER "Res/campaigns/"
class StoryGraphicalElement:public JGuiObject {
public:
float mX;
float mY;
StoryGraphicalElement(float x, float y);
};
class StoryText:public StoryGraphicalElement {
public :
string text;
int align;
StoryText(string text, float mX, float mY, string align = "center");
void Render();
void Update(float dt);
virtual ostream& toString(ostream& out) const;
};
class StoryImage:public StoryGraphicalElement {
public :
string img;
StoryImage(string img, float mX, float mY);
void Render();
void Update(float dt);
virtual ostream& toString(ostream& out) const;
};
class StoryChoice:public JGuiObject {
public:
string pageId;
string text;
int mX;
int mY;
float mX;
float mY;
bool mHasFocus;
float mScale;
float mTargetScale;
@@ -42,10 +69,12 @@ public:
class StoryDialog:public StoryPage, public JGuiListener,public JGuiController {
private:
string text;
vector<StoryGraphicalElement *>graphics;
string safeAttribute(TiXmlElement* element, string attribute);
public:
StoryDialog(TiXmlElement* el,StoryFlow * mParent);
~StoryDialog();
void Update(float dt);
void Render();
void ButtonPressed(int,int);

View File

@@ -16,6 +16,7 @@ class ThisDescriptor{
int comparisonCriterion;
virtual int match(MTGCardInstance * card) = 0;
int matchValue(int value);
virtual ~ThisDescriptor();
};
class ThisDescriptorFactory{

View File

@@ -17,8 +17,7 @@
#include "../include/GameStateOptions.h"
#include "../include/GameStateShop.h"
#include "../include/GameStateAwards.h"
//Story mode not yet ready
//#include "../include/GameStateStory.h"
#include "../include/GameStateStory.h"
#include "../include/DeckStats.h"
#include "../include/DeckMetaData.h"
#include "../include/Translate.h"
@@ -89,8 +88,10 @@ void GameApp::Create()
options.theGame = this;
//Ensure that options are partially loaded before loading files.
LOG("options.reloadProfile()");
options.reloadProfile();
LOG("Checking for music files");
//Test for Music files presence
string filepath = RESPATH;
filepath = filepath + "/" + resources.musicFile("Track0.mp3");
@@ -108,7 +109,10 @@ void GameApp::Create()
else
HasMusic = 0;
LOG("Loading Textures");
LOG("--Loading menuicons.png");
resources.RetrieveTexture("menuicons.png",RETRIEVE_MANAGE);
//Creating thes quad in this specific order allows us to have them in the correct order to call them by integer id
manaIcons[Constants::MTG_COLOR_GREEN] = resources.RetrieveQuad("menuicons.png", 2 + 0*36, 38, 32, 32, "c_green",RETRIEVE_MANAGE);
manaIcons[Constants::MTG_COLOR_BLUE] = resources.RetrieveQuad("menuicons.png", 2 + 1*36, 38, 32, 32, "c_blue",RETRIEVE_MANAGE);
@@ -121,6 +125,7 @@ void GameApp::Create()
for (int i = sizeof(manaIcons)/sizeof(manaIcons[0]) - 1; i >= 0; --i) manaIcons[i]->SetHotSpot(16,16);
LOG("--Loading Other Textures");
resources.RetrieveTexture("back.jpg",RETRIEVE_MANAGE);
JQuad * jq = resources.RetrieveQuad("back.jpg", 0, 0, 0, 0, "back",RETRIEVE_MANAGE);
if (jq) jq->SetHotSpot(jq->mWidth/2, jq->mHeight/2);
@@ -158,9 +163,11 @@ void GameApp::Create()
jq = resources.RetrieveQuad("shadow.png", 0, 0, 16, 16,"shadow",RETRIEVE_MANAGE);
jq->SetHotSpot(8, 8);
jq = resources.RetrieveQuad("phasebar.png",0,0,0,0,"phasebar",RETRIEVE_MANAGE);
LOG("Init Collection");
collection = NEW MTGAllCards();
LOG("Loading Particles");
Particles[0] = NEW hgeParticleSystem("graphics/particle1.psi", resources.GetQuad("particles"));
Particles[1] = NEW hgeParticleSystem("graphics/particle2.psi", resources.GetQuad("particles"));
Particles[2] = NEW hgeParticleSystem("graphics/particle3.psi", resources.GetQuad("particles"));
@@ -168,6 +175,7 @@ void GameApp::Create()
Particles[4] = NEW hgeParticleSystem("graphics/particle5.psi", resources.GetQuad("particles"));
Particles[5] = NEW hgeParticleSystem("graphics/particle7.psi", resources.GetQuad("particles"));
LOG("Creating Game States");
mGameStates[GAME_STATE_DECK_VIEWER] = NEW GameStateDeckViewer(this);
mGameStates[GAME_STATE_DECK_VIEWER]->Create();
@@ -186,10 +194,8 @@ void GameApp::Create()
mGameStates[GAME_STATE_AWARDS] = NEW GameStateAwards(this);
mGameStates[GAME_STATE_AWARDS]->Create();
//Story mode not yet ready
//mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this);
//mGameStates[GAME_STATE_STORY]->Create();
mGameStates[GAME_STATE_STORY] = NEW GameStateStory(this);
mGameStates[GAME_STATE_STORY]->Create();
mGameStates[GAME_STATE_TRANSITION] = NULL;
@@ -206,6 +212,7 @@ void GameApp::Create()
sprintf(buf, "size of CardPrimitive : %llu\n" , (long long unsigned int)sizeof(CardPrimitive));
OutputDebugString(buf);
LOG("Game Creation Done.");
}

View File

@@ -130,6 +130,7 @@ void GameStateMenu::Destroy()
}
void GameStateMenu::Start(){
LOG("GameStateMenu::Start");
JRenderer::GetInstance()->EnableVSync(true);
subMenuController = NULL;
SAFE_DELETE(mGuiController);
@@ -293,6 +294,7 @@ void GameStateMenu::setLang(int id){
}
void GameStateMenu::loadLangMenu(){
LOG("GameStateMenu::loadLangMenu");
subMenuController = NEW SimpleMenu(103, this, Constants::MENU_FONT, 150,60);
if (!subMenuController) return;
resetDirectory();
@@ -320,9 +322,11 @@ void GameStateMenu::loadLangMenu(){
}
}
resetDirectory();
LOG("GameStateMenu::loadLangMenu - Done");
}
void GameStateMenu::listPrimitives(){
LOG("GameStateMenu::listPrimitives");
resetDirectory();
if (!mDip){
mDip = opendir("Res/sets/primitives/");
@@ -338,6 +342,7 @@ void GameStateMenu::listPrimitives(){
}
resetDirectory();
primitivesLoadCounter = 0;
LOG("GameStateMenu::listPrimitives - Done");
}
void GameStateMenu::ensureMGuiController(){
@@ -446,8 +451,7 @@ void GameStateMenu::Update(float dt)
currentState = MENU_STATE_MAJOR_SUBMENU;
subMenuController = NEW SimpleMenu(102, this, Constants::MENU_FONT, 150,60);
if (subMenuController){
//Story mode not yet ready
//subMenuController->Add(SUBMENUITEM_STORY,"Story");
subMenuController->Add(SUBMENUITEM_STORY,"Story");
subMenuController->Add(SUBMENUITEM_CLASSIC,"Classic");
if (options[Options::MOMIR_MODE_UNLOCKED].number)
subMenuController->Add(SUBMENUITEM_MOMIR, "Momir Basic");
@@ -458,8 +462,8 @@ void GameStateMenu::Update(float dt)
subMenuController->Add(SUBMENUITEM_CANCEL, "Cancel");
}
}else{
if (mParent->gameType == GAME_TYPE_STORY)
mParent->DoTransition(TRANSITION_FADE,GAME_STATE_STORY);
if (mParent->gameType == GAME_TYPE_STORY )
mParent->DoTransition(TRANSITION_FADE, GAME_STATE_STORY);
else
mParent->DoTransition(TRANSITION_FADE,GAME_STATE_DUEL);
currentState = MENU_STATE_MAJOR_MAINMENU;

View File

@@ -71,12 +71,14 @@ void GameStateStory::Update(float dt) {
//return;
}
if (flow){
flow->Update(dt);
if (flow->currentPageId == "End") {
if (mEngine->GetButtonClick(JGE_BTN_OK) || mEngine->GetButtonClick(JGE_BTN_SEC)){
mParent->DoTransition(TRANSITION_FADE,GAME_STATE_MENU);
}
}
else {
flow->Update(dt);
}
}
}

View File

@@ -57,6 +57,7 @@ Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target, Spell
wpi = NEW WParsedInt(atoi(nbstr.c_str()));
}
nb = wpi->getValue();
delete(wpi);
end = separator;
}
@@ -560,6 +561,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
OutputDebugString("MTGABILITY: Parsing Error:");
OutputDebugString(s.c_str());
OutputDebugString("\n");
delete(cost);
return NULL;
}
@@ -757,6 +759,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
// Win the game
found = s.find("wingame");
if (found != string::npos){
Damageable * d = NULL;
if (spell) d = spell->getNextDamageableTarget();
MTGAbility * a = NEW AAWinGame(id,card,d,NULL,0,who);
a->oneShot = 1;
return a;
}
//Draw
found = s.find("draw:");
if (found != string::npos){
@@ -849,6 +861,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
Counter * counter = parseCounter(counterString,target,spell);
if (counter){
MTGAbility * a = NEW AACounter(id,card,target,counter->name.c_str(),counter->power,counter->toughness,counter->nb);
delete(counter);
a->oneShot = 1;
return a;
}
@@ -1297,11 +1310,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
game->addObserver(NEW AFireball(_id, card,spell, x));
break;
}
case 1245: //Force of Nature
{
game->addObserver(NEW AForceOfNature(_id,card));
break;
}
case 1112: //Howling Mine
{
game->addObserver(NEW AHowlingMine(_id, card));
@@ -1457,11 +1465,6 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){
game->addObserver(NEW ALivingArtifact( _id, card, card->target));
break;
}
case 1166: //Lord Of The Pit
{
game->addObserver(NEW ALordOfThePit( _id, card));
break;
}
case 1209: //Mana Short
{
Player * player = spell->getNextPlayerTarget();
@@ -1906,6 +1909,7 @@ int ActivatedAbility::reactToClick(MTGCardInstance * card){
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
game->currentlyActing()->getManaPool()->pay(cost);
cost->doPayExtra();
SAFE_DELETE(abilityCost);
abilityCost = previousManaPool->Diff(player->getManaPool());
delete previousManaPool;
}
@@ -1928,6 +1932,7 @@ int ActivatedAbility::reactToTargetClick(Targetable * object){
ManaCost * previousManaPool = NEW ManaCost(player->getManaPool());
game->currentlyActing()->getManaPool()->pay(cost);
cost->doPayExtra();
SAFE_DELETE(abilityCost);
abilityCost = previousManaPool->Diff(player->getManaPool());
delete previousManaPool;
}
@@ -1938,9 +1943,12 @@ int ActivatedAbility::reactToTargetClick(Targetable * object){
}
ActivatedAbility::~ActivatedAbility(){
if (!isClone){
//Ok, this will probably lead to crashes, maybe with lord abilities involving "X" costs.
// If that's the case, we need to improve the clone() method of GenericActivatedAbility and GenericTargetAbility, I think
// Erwan 2004/04/25
//if (!isClone){
SAFE_DELETE(abilityCost);
}
//}
}
ostream& ActivatedAbility::toString(ostream& out) const
@@ -2011,7 +2019,9 @@ void TargetAbility::Render(){
int TargetAbility::resolve(){
Targetable * t = tc->getNextTarget();
if (t && ability){
source->X = abilityCost->Diff(cost)->hasX();
ManaCost * diff = abilityCost->Diff(cost);
source->X = diff->hasX();
delete (diff);
ability->target = t;
if (ability->oneShot) return ability->resolve();
MTGAbility * a = ability->clone();

View File

@@ -70,9 +70,9 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
OutputDebugString("Counter\n");
size_t counter_start = value.find("(");
size_t counter_end = value.find(")", counter_start);
AbilityFactory * abf = NEW AbilityFactory();
AbilityFactory abf;
string counterString = value.substr(counter_start+1,counter_end-counter_start-1);
Counter * counter = abf->parseCounter(counterString,c);
Counter * counter = abf.parseCounter(counterString,c);
size_t separator = value.find(",",counter_start);
size_t separator2 = string::npos;
if (separator != string::npos) {

View File

@@ -8,9 +8,64 @@
#include <JGE.h>
#include <JFileSystem.h>
StoryGraphicalElement::StoryGraphicalElement(float x, float y): JGuiObject(0), mX(x),mY(y) {
}
StoryText::StoryText(string text, float _mX, float _mY, string _align):StoryGraphicalElement(_mX,_mY), text(text) {
align = JGETEXT_LEFT;
if (_align.compare("center") == 0) {
align = JGETEXT_CENTER;
}else if (_align.compare("right") == 0) {
align = JGETEXT_RIGHT;
}
if (align == JGETEXT_CENTER && mX == 0){
mX = SCREEN_WIDTH/2;
}
}
void StoryText::Render() {
JLBFont * mFont = resources.GetJLBFont(Constants::MAIN_FONT);
mFont->SetColor(ARGB(200,255,255,255));
mFont->SetScale(1.0);
mFont->DrawString(text.c_str(), mX, mY, align);
}
void StoryText::Update(float dt){
//Nothing for now
}
ostream& StoryText::toString(ostream& out) const
{
return out << "StoryText ::: text : " << text;
}
StoryImage::StoryImage(string img, float mX, float mY):StoryGraphicalElement(mX,mY), img(img) {
}
void StoryImage::Render() {
JQuad * quad = resources.RetrieveQuad(img);
if (quad) {
float x = mX;
if (mX == -1) {
x = SCREEN_WIDTH/2;
quad->SetHotSpot(quad->mWidth/2, 0);
}
JRenderer::GetInstance()->RenderQuad(quad,x, mY);
}
}
void StoryImage::Update(float dt){
//Nothing for now
}
ostream& StoryImage::toString(ostream& out) const
{
return out << "StoryImage ::: img : " << img;
}
StoryPage::StoryPage(StoryFlow * mParent):mParent(mParent){
}
StoryFlow::StoryFlow(string folder): folder(folder){
string path = "campaigns/";
path.append(folder).append("/story.xml");
@@ -155,15 +210,43 @@ void StoryDuel::Render(){
game->Render();
}
string StoryDialog::safeAttribute(TiXmlElement* element, string attribute) {
string s;
if (element->Attribute(attribute.c_str())){
s = element->Attribute(attribute.c_str());
}
return s;
}
StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):JGuiListener(), JGuiController(1,NULL), StoryPage(mParent) {
StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):StoryPage(mParent), JGuiListener(), JGuiController(1,NULL) {
for (TiXmlNode* node = root->FirstChild(); node; node = node->NextSibling()) {
TiXmlElement* element = node->ToElement();
if (element) {
if (strcmp(element->Value(), "text")==0) {
const char* textC = element->GetText();
text = textC;
string sX = safeAttribute(element, "x");
float x = atof(sX.c_str());
string sY = safeAttribute(element,"y");
float y = atof(sY.c_str());
string align = safeAttribute(element,"align");
const char* textC = element->GetText();
string text = textC;
graphics.push_back(NEW StoryText(text,x,y,align));
}
else if (strcmp(element->Value(), "img")==0) {
string sX = safeAttribute(element,"x");
float x = atof(sX.c_str());
//special case to force center
if (sX.compare("") == 0 ){
x = -1;
}
string sY = safeAttribute(element,"y");
float y = atof(sY.c_str());
const char* imgC = element->GetText();
string img = imgC;
img = string("campaigns/").append(mParent->folder).append("/").append(img);
graphics.push_back(NEW StoryImage(img,x,y));
}
else if (strcmp(element->Value(), "answer")==0){
string id = element->Attribute("goto");
@@ -183,14 +266,16 @@ StoryDialog::StoryDialog(TiXmlElement* root, StoryFlow * mParent):JGuiListener()
void StoryDialog::Update(float dt){
JGuiController::Update(dt);
for (size_t i = 0; i < graphics.size(); ++i){
graphics[i]->Update(dt);
}
}
void StoryDialog::Render() {
JLBFont * mFont = resources.GetJLBFont(Constants::MAIN_FONT);
mFont->SetColor(ARGB(255,255,255,255));
mFont->SetScale(1.0);
mFont->DrawString(text.c_str(), 0, 0);
for (size_t i = 0; i < graphics.size(); ++i){
graphics[i]->Render();
}
JGuiController::Render();
}
@@ -198,6 +283,12 @@ void StoryDialog::ButtonPressed(int controllerid,int controlid) {
mParent->gotoPage(((StoryChoice *)mObjects[controlid])->pageId);
}
StoryDialog::~StoryDialog(){
for (size_t i = 0; i < graphics.size(); ++i){
delete(graphics[i]);
}
}
StoryPage * StoryFlow::loadPage(TiXmlElement* element){
TiXmlNode* typeNode = element->FirstChild("type");
if (!typeNode) return NULL;

View File

@@ -215,13 +215,14 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
size_t start = attribute.find("{");
size_t end = attribute.find("}");
string counterString = attribute.substr(start+1,end-start-1);
AbilityFactory * abf = NEW AbilityFactory();
Counter * counter = abf->parseCounter(counterString,card);
AbilityFactory abf;
Counter * counter = abf.parseCounter(counterString,card);
if (counter) {
cd->counterName = counter->name;
cd->counterNB = counter->nb;
cd->counterPower = counter->power;
cd->counterToughness = counter->toughness;
delete(counter);
}
if (minus) {
cd->counterComparisonMode = COMPARISON_LESS;

View File

@@ -5,6 +5,10 @@
#include "../include/CardDescriptor.h"
ThisDescriptor::~ThisDescriptor(){
//nothing to do for now
}
//Returns the amount by which a value passes the comparison.
int ThisDescriptor::matchValue(int value){
switch (comparisonMode){
@@ -98,8 +102,8 @@ ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s){
size_t start = s.find("{");
size_t end = s.find("}");
string counterString = s.substr(start+1,end-start-1);
AbilityFactory * abf = NEW AbilityFactory();
Counter * counter = abf->parseCounter(counterString,NULL);
AbilityFactory abf;
Counter * counter = abf.parseCounter(counterString,NULL);
if (counter) {
if (criterionFound) counter->nb = criterion;
ThisCounter * td = NEW ThisCounter(counter);

View File

@@ -534,6 +534,11 @@ string WResourceManager::graphicsFile(const string filename){
if(fileOK(buf,true))
return buf;
//Failure. Check raw faile.
sprintf(buf,"%s",filename.c_str());
if(fileOK(buf,true))
return buf;
//Complete abject failure. Probably a crash...
return graphdir;
}