added abilities:
proliferate
ProliferateChooser:new targetchooser for cards with counter and poison counters "proliferation".
MenuAbility:new internal ability to create custom menus of abilities which can be activated in sequence one after another.
multikicker, syntax kicker=multi{b}
works with variable word "kicked", the amount of times it was kicked.
target=<number>tc,target=<upto:>tc,target=<anyamount>tc,target(<number>tc),target(<upto:>tc),target(<anynumber>tc);
multitarget is now supported with the exception of "devided any way you choose" which can not be supported becuase we allow detoggling of targeted cards with a "second" click....so you can not click the same card 2 times to add it to the targets list twice for example.
this is minor, as the bulk of multitarget is not "devided"
removed 's' parsing for multitarget, added a limit of 1000 to "unlimited" for easier handling; we currently can't handle activation of an ability on a 1000 cards very well on any platform(infact i don't suggest it)
Countershroud(counterstring), this MTGAbility allows you to denote that a card can not have counters of the type "counterstring" put on it.
"any" is for no counters allowed at all. this is a replacement effect. cards state that they can still be the targets of counter effects, however on resolve nothing is placed on them instead.
@counteradded(counterstring) from(target):,@counterremoved(counterstring) from(target):: these are triggers for cards which state "whenever you add a counter of "counterstring" to "target"; added counterEvents struct;
other changes:
added support for ai handling of multitargeted spells.
changed a few of delete( into SAFE_DELETE(, safed up a couple areas where they did not seem safe to me;
added better handling of menus presented to ai, it will try to select the best based on eff returns.
added varible lastactioncontroller for ai use, it keeps it truely from ever tripping over itself and brings ai more inline with MTG rules.
converted TC into a protected member.
added "abilitybelongsto" string to tc, and set "owner" of the tc. a tc should never belong to "no one" it should always have a owner.
abilitybelongs to string is solely for easier debugging, i found it was a pain to never know what ability created a tc while i coded multitarget. the owner of the tc is the only one that should be using it, if an ability needs to declare the opponent as the owner (choose discard which is currently unsupported for example) this will allow us to better handle that situation by setting the tc owner in the ability which called it.
rewrote the logic of "checkonly" in ai choose targets, the only time it is "checkonly" is when it is trying to see if it had a target for a spell before it cast it, i now set this in the actual function call instead, the old method was far to error prone.
wrote logic for ai checking of menu objects presented to it,
ai will now make better choices when a menu is presented to it based on what it already knows. this changes it from it's old method of "just click the first option".
taught ai how to use multi-mana producers such as birds and duel lands by adding a method for it to find it's mana for a payment. it can effectively use cards like birds of paradise and sol ring(without locking up). It's primary method of pMana searching was maintain for performance(no need to deep search if we have it in pMana).
added a vector to actionlayer to store mana abilities for pMana. this provides us with a dramatic improvement when mana lords are present by reducing the amount of objects that need checking when ai checks pMana.
with 80 mana objects and a ton of lords one instance i checked went from 8000ish checks down to 80<===big difference.
added "tapped" green coloring(sorry i missed that!)...added red coloring to current actionLayers current action card (usually the source).
changed "type(" restrictions second amount from atoi into wparsedint for more flexiable coding.
add "&" parsing to CD targetchooser, removed "iscolorandcolor" variables and functions becuase they were a hack the real fix was this.
cretaure[dragon&black&blue] a creature that is a dragon, and black and also blue.
changed some of the ai computeactions and
removed unneeded gaurds in ai chooseblockers, they did more harm then good.
249 lines
6.2 KiB
C++
249 lines
6.2 KiB
C++
/*
|
|
* Wagic, The Homebrew ?! is licensed under the BSD license
|
|
* See LICENSE in the Folder's root
|
|
* http://wololo.net/wagic/
|
|
*/
|
|
|
|
#ifndef _SPELLSTACK_H_
|
|
#define _SPELLSTACK_H_
|
|
|
|
#define MAX_SPELL_TARGETS 10
|
|
|
|
|
|
#define ACTION_SPELL 10
|
|
#define ACTION_DAMAGE 11
|
|
#define ACTION_DAMAGES 12
|
|
#define ACTION_NEXTGAMEPHASE 13
|
|
#define ACTION_DRAW 14
|
|
#define ACTION_PUTINGRAVEYARD 15
|
|
#define ACTION_ABILITY 16
|
|
|
|
#define NOT_RESOLVED -2
|
|
#define RESOLVED_OK 1
|
|
#define RESOLVED_NOK -1
|
|
|
|
#include "PlayGuiObject.h"
|
|
#include "GuiLayers.h"
|
|
#include "TargetsList.h"
|
|
#include "Targetable.h"
|
|
|
|
#include "WResource_Fwd.h"
|
|
|
|
class GuiLayer;
|
|
class PlayGuiObject;
|
|
class MTGCardInstance;
|
|
class GameObserver;
|
|
class Player;
|
|
class Damageable;
|
|
class MTGAbility;
|
|
class Targetable;
|
|
class DamageStack;
|
|
class ManaCost;
|
|
class TargetChooser;
|
|
|
|
|
|
#define ACTIONSTACK_STANDARD 0
|
|
#define ACTIONSTACK_TARGET 1
|
|
|
|
class Interruptible: public PlayGuiObject, public Targetable
|
|
{
|
|
public:
|
|
//TODO : remove these when they are back in PlayGuiObject
|
|
float x, y;
|
|
|
|
int state, display;
|
|
MTGCardInstance * source;
|
|
virtual void Entering()
|
|
{
|
|
mHasFocus = true;
|
|
}
|
|
|
|
virtual bool Leaving(JButton key)
|
|
{
|
|
mHasFocus = false;
|
|
return true;
|
|
}
|
|
|
|
virtual bool ButtonPressed()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual int resolve()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
virtual void Render()
|
|
{
|
|
}
|
|
|
|
int typeAsTarget()
|
|
{
|
|
return TARGET_STACKACTION;
|
|
}
|
|
|
|
Interruptible(int inID = 0, bool hasFocus = false)
|
|
: PlayGuiObject(40, x, y, inID, hasFocus), state(NOT_RESOLVED), display(0), source(NULL)
|
|
{
|
|
}
|
|
|
|
virtual const string getDisplayName() const;
|
|
void Render(MTGCardInstance * source, JQuad * targetQuad, string alt1, string alt2, string action, bool bigQuad = false);
|
|
|
|
virtual int receiveEvent(WEvent * event)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#if defined (WIN32) || defined (LINUX) || defined (IOS)
|
|
virtual void Dump();
|
|
#endif
|
|
|
|
protected:
|
|
float GetVerticalTextOffset() const;
|
|
};
|
|
|
|
class NextGamePhase: public Interruptible
|
|
{
|
|
public:
|
|
int resolve();
|
|
bool extraDamagePhase();
|
|
void Render();
|
|
virtual ostream& toString(ostream& out) const;
|
|
virtual const string getDisplayName() const;
|
|
NextGamePhase(int id);
|
|
};
|
|
|
|
class Spell: public Interruptible
|
|
{
|
|
protected:
|
|
|
|
public:
|
|
MTGGameZone * from;
|
|
TargetChooser * tc;
|
|
ManaCost * cost;
|
|
int payResult;
|
|
int computeX(MTGCardInstance * card);
|
|
Spell(MTGCardInstance* _source);
|
|
Spell(int id, MTGCardInstance* _source, TargetChooser *_tc, ManaCost * _cost, int payResult);
|
|
~Spell();
|
|
int resolve();
|
|
void Render();
|
|
bool FullfilledAlternateCost(const int &costType);
|
|
const string getDisplayName() const;
|
|
virtual ostream& toString(ostream& out) const;
|
|
MTGCardInstance * getNextCardTarget(MTGCardInstance * previous = 0);
|
|
Player * getNextPlayerTarget(Player * previous = 0);
|
|
Damageable * getNextDamageableTarget(Damageable * previous = 0);
|
|
Interruptible * getNextInterruptible(Interruptible * previous, int type);
|
|
Spell * getNextSpellTarget(Spell * previous = 0);
|
|
Damage * getNextDamageTarget(Damage * previous = 0);
|
|
Targetable * getNextTarget(Targetable * previous = 0, int type = -1);
|
|
int getNbTargets();
|
|
};
|
|
|
|
class StackAbility: public Interruptible
|
|
{
|
|
public:
|
|
MTGAbility * ability;
|
|
int resolve();
|
|
void Render();
|
|
virtual ostream& toString(ostream& out) const;
|
|
virtual const string getDisplayName() const;
|
|
StackAbility(int id, MTGAbility * _ability);
|
|
};
|
|
|
|
class PutInGraveyard: public Interruptible {
|
|
public:
|
|
MTGCardInstance * card;
|
|
int removeFromGame;
|
|
int resolve();
|
|
void Render();
|
|
virtual ostream& toString(ostream& out) const;
|
|
PutInGraveyard(int id, MTGCardInstance * _card);
|
|
};
|
|
|
|
|
|
class DrawAction: public Interruptible
|
|
{
|
|
public:
|
|
int nbcards;
|
|
Player * player;
|
|
int resolve();
|
|
void Render();
|
|
virtual ostream& toString(ostream& out) const;
|
|
DrawAction(int id, Player * _player, int _nbcards);
|
|
};
|
|
|
|
class LifeAction: public Interruptible
|
|
{
|
|
public:
|
|
int amount;
|
|
Damageable * target;
|
|
int resolve();
|
|
void Render();
|
|
virtual ostream& toString(ostream& out) const;
|
|
LifeAction(int id, Damageable * _target, int amount);
|
|
};
|
|
|
|
class ActionStack :public GuiLayer
|
|
{
|
|
protected:
|
|
JQuadPtr pspIcons[8];
|
|
GameObserver* game;
|
|
int interruptDecision[2];
|
|
float timer;
|
|
int currentState;
|
|
int mode;
|
|
int checked;
|
|
|
|
public:
|
|
|
|
enum
|
|
{
|
|
NOT_DECIDED = 0,
|
|
INTERRUPT = -1,
|
|
DONT_INTERRUPT = 1,
|
|
DONT_INTERRUPT_ALL = 2,
|
|
};
|
|
Player * lastActionController;
|
|
int setIsInterrupting(Player * player);
|
|
int count( int type = 0 , int state = 0 , int display = -1);
|
|
int getActionElementFromCard(MTGCardInstance * card);
|
|
Interruptible * getPrevious(Interruptible * next, int type = 0, int state = 0 , int display = -1);
|
|
int getPreviousIndex(Interruptible * next, int type = 0, int state = 0 , int display = -1);
|
|
Interruptible * getNext(Interruptible * previous, int type = 0, int state = 0 , int display = -1);
|
|
int getNextIndex(Interruptible * previous, int type = 0, int state = 0 , int display = -1);
|
|
void Fizzle(Interruptible * action);
|
|
Interruptible * getAt(int id);
|
|
void cancelInterruptOffer(int cancelMode = 1);
|
|
void endOfInterruption();
|
|
Interruptible * getLatest(int state);
|
|
Player * askIfWishesToInterrupt;
|
|
int garbageCollect();
|
|
int addAction(Interruptible * interruptible);
|
|
Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult, int storm);
|
|
int AddNextGamePhase();
|
|
int AddNextCombatStep();
|
|
int addPutInGraveyard(MTGCardInstance * card);
|
|
int addDraw(Player * player, int nbcards = 1);
|
|
int addLife(Damageable * _target,int amount = 0);
|
|
int addDamage(MTGCardInstance * _source, Damageable * target, int _damage);
|
|
int addAbility(MTGAbility * ability);
|
|
void Update(float dt);
|
|
bool CheckUserInput(JButton key);
|
|
virtual void Render();
|
|
ActionStack(GameObserver* game);
|
|
int resolve();
|
|
int has(Interruptible * action);
|
|
int has(MTGAbility * ability);
|
|
int receiveEventPlus(WEvent * event);
|
|
#if defined (WIN32) || defined (LINUX) || defined (IOS)
|
|
void Dump();
|
|
#endif
|
|
|
|
};
|
|
|
|
#endif
|