mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Third draft of AbilityFactory. Overwrites changes in AbilityFactory from r2620.
Renamed DealDamage to AbilityFactory_DealDamage. Now supports the spell version. (Shock) All static modifiers removed. Added support for Buyback in the CardFactory handler for AbilityFactory cards.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -5053,6 +5053,7 @@ src/com/esotericsoftware/minlog/Log.java svneol=native#text/plain
|
||||
src/forge/Ability.java svneol=native#text/plain
|
||||
src/forge/AbilityFactory.java -text svneol=native#text/plain
|
||||
src/forge/AbilityFactory_Counters.java -text svneol=native#text/plain
|
||||
src/forge/AbilityFactory_DealDamage.java -text svneol=native#text/plain
|
||||
src/forge/Ability_Activated.java svneol=native#text/plain
|
||||
src/forge/Ability_Cost.java -text svneol=native#text/plain
|
||||
src/forge/Ability_Hand.java svneol=native#text/plain
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Human Wizard
|
||||
Text:no text
|
||||
PT:1/1
|
||||
# K:abDamageTgtCP T:1
|
||||
A:AB$DealDamage|Cost$T|Tgt$TgtCP|NumDmg$1|SpellDescription$Deal 1 damage to target creature or player.
|
||||
A:AB$DealDamage|Cost$T|Tgt$TgtCP|NumDmg$1|SpellDescription$Prodigal Pyromancer deals 1 damage to target creature or player.
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://resources.wizards.com/magic/cards/plc/en-us/card122338.jpg
|
||||
End
|
||||
|
||||
@@ -2,7 +2,8 @@ Name:Shock
|
||||
ManaCost:R
|
||||
Types:Instant
|
||||
Text:no text
|
||||
K:spDamageTgtCP:2
|
||||
# K:spDamageTgtCP:2
|
||||
A:SP$DealDamage|Cost$R|Tgt$TgtCP|NumDmg$2|SpellDescription$Shock deals 2 damage to target creature or player.
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/shock.jpg
|
||||
End
|
||||
|
||||
@@ -10,7 +10,7 @@ public class AbilityFactory {
|
||||
{
|
||||
return hostC;
|
||||
}
|
||||
|
||||
|
||||
private HashMap<String,String> mapParams = new HashMap<String,String>();
|
||||
|
||||
public HashMap<String,String> getMapParams()
|
||||
@@ -57,11 +57,6 @@ public class AbilityFactory {
|
||||
return abTgt;
|
||||
}
|
||||
|
||||
private boolean isCurse = false;
|
||||
public boolean isCurse(){
|
||||
return isCurse;
|
||||
}
|
||||
|
||||
private boolean hasSubAb = false;
|
||||
|
||||
public boolean hasSubAbility()
|
||||
@@ -69,14 +64,17 @@ public class AbilityFactory {
|
||||
return hasSubAb;
|
||||
}
|
||||
|
||||
private static boolean hasSpDesc = false;
|
||||
private boolean hasSpDesc = false;
|
||||
|
||||
public boolean hasSpDescription()
|
||||
{
|
||||
return hasSpDesc;
|
||||
}
|
||||
|
||||
public SpellAbility getAbility(String abString, final Card hostCard){
|
||||
//*******************************************************
|
||||
|
||||
public SpellAbility getAbility(String abString, Card hostCard){
|
||||
|
||||
SpellAbility SA = null;
|
||||
|
||||
hostC = hostCard;
|
||||
@@ -99,19 +97,18 @@ public class AbilityFactory {
|
||||
mapParams.put(aa[0], aa[1]);
|
||||
}
|
||||
|
||||
String abAPI = "";
|
||||
String spAPI = "";
|
||||
// parse universal parameters
|
||||
|
||||
// additional ability types here
|
||||
String API = "";
|
||||
if (mapParams.containsKey("AB"))
|
||||
{
|
||||
isAb = true;
|
||||
abAPI = mapParams.get("AB");
|
||||
API = mapParams.get("AB");
|
||||
}
|
||||
else if (mapParams.containsKey("SP"))
|
||||
{
|
||||
isSp = true;
|
||||
spAPI = mapParams.get("SP");
|
||||
API = mapParams.get("SP");
|
||||
}
|
||||
else
|
||||
throw new RuntimeException("AbilityFactory : getAbility -- no API in " + hostCard.getName());
|
||||
@@ -121,10 +118,14 @@ public class AbilityFactory {
|
||||
throw new RuntimeException("AbilityFactory : getAbility -- no Cost in " + hostCard.getName());
|
||||
abCost = new Ability_Cost(mapParams.get("Cost"), hostCard.getName(), isAb);
|
||||
|
||||
|
||||
if (mapParams.containsKey("ValidTgts"))
|
||||
{
|
||||
hasValid = true;
|
||||
isTargeted = true;
|
||||
abTgt = new Target("TgtV");
|
||||
abTgt.setValidTgts(mapParams.get("ValidTgts").split(","));
|
||||
abTgt.setVTSelection(mapParams.get("TgtPrompt"));
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("ValidCards"))
|
||||
@@ -133,31 +134,18 @@ public class AbilityFactory {
|
||||
if (mapParams.containsKey("Tgt"))
|
||||
{
|
||||
isTargeted = true;
|
||||
abTgt = new Target(mapParams.get("Tgt"));
|
||||
}
|
||||
|
||||
if (isTargeted)
|
||||
{
|
||||
if (hasValid)
|
||||
abTgt = new Target("TgtV", mapParams.get("TgtPrompt"), mapParams.get("ValidTgts").split(","));
|
||||
else
|
||||
abTgt = new Target(mapParams.get("Tgt"));
|
||||
}
|
||||
else{
|
||||
abTgt = null;
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("IsCurse")){
|
||||
isCurse = true;
|
||||
}
|
||||
hasSubAb = mapParams.containsKey("SubAbility");
|
||||
|
||||
if (mapParams.containsKey("SubAbility"))
|
||||
hasSubAb = true;
|
||||
|
||||
if (mapParams.containsKey("SpellDescription"))
|
||||
hasSpDesc = true;
|
||||
hasSpDesc = mapParams.containsKey("SpellDescription");
|
||||
|
||||
|
||||
if (abAPI.equals("DealDamage"))
|
||||
// ***********************************
|
||||
// Match API keywords
|
||||
|
||||
if (API.equals("DealDamage"))
|
||||
{
|
||||
final int NumDmg[] = {-1};
|
||||
final String NumDmgX[] = {"none"};
|
||||
@@ -171,37 +159,42 @@ public class AbilityFactory {
|
||||
NumDmg[0] = Integer.parseInt(tmpND);
|
||||
}
|
||||
|
||||
if (isAb)
|
||||
SA = DealDamage.getAbility(this, NumDmg[0], NumDmgX[0]);
|
||||
AbilityFactory_DealDamage dd = new AbilityFactory_DealDamage();
|
||||
|
||||
if (isAb)
|
||||
SA = dd.getAbility(this, NumDmg[0], NumDmgX[0]);
|
||||
else if (isSp)
|
||||
SA = DealDamage.getSpell(this);
|
||||
SA = dd.getSpell(this, NumDmg[0], NumDmgX[0]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// additional keywords here
|
||||
if (abAPI.equals("PutCounter")){
|
||||
if (isAb)
|
||||
SA = AbilityFactory_Counters.createAbilityPutCounters(this);
|
||||
if (isSp){
|
||||
// todo: createSpellPutCounters
|
||||
}
|
||||
}
|
||||
// additional API keywords here
|
||||
|
||||
|
||||
// *********************************************
|
||||
// set universal properties of the SpellAbility
|
||||
if (isSp){
|
||||
// Ability_Activated sets abTgt and abCost in the constructor so this only needs to be set for Spells
|
||||
// Once Spells are more compatible with Tgt and abCost this block should be removed
|
||||
if (isTargeted)
|
||||
SA.setTarget(abTgt);
|
||||
|
||||
SA.setPayCosts(abCost);
|
||||
}
|
||||
if (isTargeted)
|
||||
{
|
||||
//if (isAb)
|
||||
SA.setTarget(abTgt);
|
||||
|
||||
}
|
||||
|
||||
//if (isAb)
|
||||
SA.setPayCosts(abCost);
|
||||
|
||||
if (hasSpDesc)
|
||||
SA.setDescription(abCost.toString() + mapParams.get("SpellDescription"));
|
||||
{
|
||||
String desc = mapParams.get("SpellDescription");
|
||||
if (isAb)
|
||||
desc = abCost.toString() + desc;
|
||||
|
||||
SA.setDescription(desc);
|
||||
}
|
||||
|
||||
return SA;
|
||||
|
||||
return SA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
233
src/forge/AbilityFactory_DealDamage.java
Normal file
233
src/forge/AbilityFactory_DealDamage.java
Normal file
@@ -0,0 +1,233 @@
|
||||
package forge;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class AbilityFactory_DealDamage {
|
||||
|
||||
private AbilityFactory AF = null;
|
||||
|
||||
private AbilityFactory getAF(){
|
||||
return AF;
|
||||
}
|
||||
private int nDamage = -1;
|
||||
|
||||
private String XDamage = "none";
|
||||
|
||||
private boolean TgtOpp = false;
|
||||
|
||||
public SpellAbility getAbility(final AbilityFactory af, final int NumDmg, final String NumDmgX)
|
||||
{
|
||||
AF = af;
|
||||
nDamage = NumDmg;
|
||||
XDamage = NumDmgX;
|
||||
|
||||
if (AF.getMapParams().get("Tgt").equals("TgtOpp"))
|
||||
TgtOpp = true;
|
||||
|
||||
final SpellAbility abDamage = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt())
|
||||
{
|
||||
private static final long serialVersionUID = -7560349014757367722L;
|
||||
|
||||
@Override
|
||||
public boolean canPlay(){
|
||||
return (Cost_Payment.canPayAdditionalCosts(AF.getAbCost(), this)
|
||||
&& CardFactoryUtil.canUseAbility(AF.getHostCard())
|
||||
&& super.canPlay());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return doCanPlayAI(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
doResolve(this);
|
||||
AF.getHostCard().setAbilityUsed(AF.getHostCard().getAbilityUsed() + 1);
|
||||
|
||||
}
|
||||
};//Ability_Activated
|
||||
|
||||
return abDamage;
|
||||
}
|
||||
|
||||
public SpellAbility getSpell(final AbilityFactory af, final int NumDmg, final String NumDmgX)
|
||||
{
|
||||
AF = af;
|
||||
nDamage = NumDmg;
|
||||
XDamage = NumDmgX;
|
||||
|
||||
if (AF.getMapParams().get("Tgt").equals("TgtOpp"))
|
||||
TgtOpp = true;
|
||||
|
||||
final SpellAbility spDealDamage = new Spell(AF.getHostCard()) {
|
||||
private static final long serialVersionUID = 7239608350643325111L;
|
||||
|
||||
@Override
|
||||
public boolean canPlay(){
|
||||
return (Cost_Payment.canPayAdditionalCosts(AF.getAbCost(), this)
|
||||
&& super.canPlay());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return doCanPlayAI(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
doResolve(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}; // Spell
|
||||
|
||||
return spDealDamage;
|
||||
}
|
||||
|
||||
private int getNumDamage() {
|
||||
if(nDamage != -1) return nDamage;
|
||||
|
||||
if(!XDamage.equals("none"))
|
||||
return CardFactoryUtil.xCount(AF.getHostCard(), XDamage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean shouldTgtP(int d) {
|
||||
PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer);
|
||||
CardList hand = new CardList(compHand.getCards());
|
||||
|
||||
if(AF.isSpell() && hand.size() > 7) // anti-discard-at-EOT
|
||||
return true;
|
||||
|
||||
if(AllZone.Human_Life.getLife() - d < 10) // if damage from this spell would drop the human to less than 10 life
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Card chooseTgtC(final int d) {
|
||||
// Combo alert!!
|
||||
PlayerZone compy = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
|
||||
CardList cPlay = new CardList(compy.getCards());
|
||||
if(cPlay.size() > 0) for(int i = 0; i < cPlay.size(); i++)
|
||||
if(cPlay.get(i).getName().equals("Stuffy Doll")) return cPlay.get(i);
|
||||
|
||||
PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
|
||||
CardList hPlay = new CardList(human.getCards());
|
||||
hPlay = hPlay.filter(new CardListFilter() {
|
||||
public boolean addCard(Card c) {
|
||||
// will include creatures already dealt damage
|
||||
return c.isCreature() && ((c.getNetDefense() + c.getDamage()) <= d)
|
||||
&& CardFactoryUtil.canTarget(AF.getHostCard(), c);
|
||||
}
|
||||
});
|
||||
|
||||
if(hPlay.size() > 0) {
|
||||
Card best = hPlay.get(0);
|
||||
|
||||
if(hPlay.size() > 1) {
|
||||
for(int i = 1; i < hPlay.size(); i++) {
|
||||
Card b = hPlay.get(i);
|
||||
// choose best overall creature?
|
||||
if(b.getSpellAbility().length > best.getSpellAbility().length
|
||||
|| b.getKeyword().size() > best.getKeyword().size()
|
||||
|| b.getNetAttack() > best.getNetAttack()) best = b;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean doCanPlayAI(SpellAbility saMe)
|
||||
{
|
||||
// temporarily disabled until better AI
|
||||
if (AF.getAbCost().getSacCost()) return false;
|
||||
if (AF.getAbCost().getSubCounter()) return false;
|
||||
if (AF.getAbCost().getLifeCost()) return false;
|
||||
|
||||
if (!ComputerUtil.canPayCost(saMe))
|
||||
return false;
|
||||
|
||||
int damage = getNumDamage();
|
||||
|
||||
boolean rr = false;
|
||||
|
||||
if (AF.isAbility())
|
||||
{
|
||||
Random r = new Random(); // prevent run-away activations
|
||||
if(r.nextFloat() <= Math.pow(.6667, AF.getHostCard().getAbilityUsed()))
|
||||
rr = true;
|
||||
}
|
||||
else if (AF.isSpell())
|
||||
rr = true;
|
||||
|
||||
if(AF.getAbTgt().canTgtCreaturePlayer()) {
|
||||
if(shouldTgtP(damage)) {
|
||||
saMe.setTargetPlayer(Constant.Player.Human);
|
||||
return rr;
|
||||
}
|
||||
|
||||
Card c = chooseTgtC(damage);
|
||||
if(c != null) {
|
||||
saMe.setTargetCard(c);
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
if(AF.getAbTgt().canTgtPlayer() || TgtOpp == true) {
|
||||
saMe.setTargetPlayer(Constant.Player.Human);
|
||||
return rr;
|
||||
}
|
||||
|
||||
if(AF.getAbTgt().canTgtCreature()) {
|
||||
Card c = chooseTgtC(damage);
|
||||
if(c != null) {
|
||||
saMe.setTargetCard(c);
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private void doResolve(SpellAbility saMe)
|
||||
{
|
||||
int damage = getNumDamage();
|
||||
String tgtP = "";
|
||||
|
||||
if(TgtOpp == true) {
|
||||
tgtP = AllZone.GameAction.getOpponent(AF.getHostCard().getController());
|
||||
saMe.setTargetPlayer(tgtP);
|
||||
}
|
||||
|
||||
Card c = saMe.getTargetCard();
|
||||
if(c != null) {
|
||||
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(AF.getHostCard(), c)) {
|
||||
AllZone.GameAction.addDamage(c, AF.getHostCard(), damage);
|
||||
tgtP = c.getController();
|
||||
|
||||
if(AF.hasSubAbility())
|
||||
CardFactoryUtil.doDrawBack(AF.getMapParams().get("SubAbility"), damage,
|
||||
AF.getHostCard().getController(), AllZone.GameAction.getOpponent(AF.getHostCard().getController()),
|
||||
tgtP, AF.getHostCard(), c, saMe);
|
||||
|
||||
}
|
||||
} else {
|
||||
tgtP = saMe.getTargetPlayer();
|
||||
AllZone.GameAction.addDamage(tgtP, AF.getHostCard(), damage);
|
||||
|
||||
if(AF.hasSubAbility())
|
||||
CardFactoryUtil.doDrawBack(AF.getMapParams().get("SubAbility"), damage,
|
||||
AF.getHostCard().getController(), AllZone.GameAction.getOpponent(AF.getHostCard().getController()),
|
||||
tgtP, AF.getHostCard(), null, saMe);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6093,14 +6093,32 @@ public class CardFactory implements NewConstants {
|
||||
// AbilityFactory cards
|
||||
ArrayList<String> IA = card.getIntrinsicAbilities();
|
||||
if (IA.size() > 0)
|
||||
{
|
||||
{
|
||||
if (card.isInstant() || card.isSorcery())
|
||||
card.clearSpellAbility();
|
||||
|
||||
for (int i=0; i<IA.size(); i++){
|
||||
AbilityFactory AF = new AbilityFactory();
|
||||
card.addSpellAbility(AF.getAbility(IA.get(i), card));
|
||||
for (int i=0; i<IA.size(); i++)
|
||||
{
|
||||
AbilityFactory AF = new AbilityFactory();
|
||||
SpellAbility sa = AF.getAbility(IA.get(i), card);
|
||||
|
||||
card.addSpellAbility(sa);
|
||||
|
||||
String bbCost = card.getSVar("Buyback");
|
||||
if (!bbCost.equals(""))
|
||||
{
|
||||
SpellAbility bbSA = sa.copy();
|
||||
bbSA.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
|
||||
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
|
||||
bbSA.setDescription(sb.toString());
|
||||
bbSA.setIsBuyBackAbility(true);
|
||||
|
||||
card.addSpellAbility(bbSA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user