mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
add a SetLife AbilityFactory. Mostly done by Sol, but I added a little more AI smarts. Add Blessed Wind and Magister Sphinx as examples.
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -634,6 +634,7 @@ res/cardsfolder/blazing_specter.txt -text svneol=native#text/plain
|
|||||||
res/cardsfolder/bleak_coven_vampires.txt -text svneol=native#text/plain
|
res/cardsfolder/bleak_coven_vampires.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/blessed_orator.txt -text svneol=native#text/plain
|
res/cardsfolder/blessed_orator.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/blessed_reversal.txt -text svneol=native#text/plain
|
res/cardsfolder/blessed_reversal.txt -text svneol=native#text/plain
|
||||||
|
res/cardsfolder/blessed_wind.txt svneol=native#text/plain
|
||||||
res/cardsfolder/blessed_wine.txt -text svneol=native#text/plain
|
res/cardsfolder/blessed_wine.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/blessing.txt -text svneol=native#text/plain
|
res/cardsfolder/blessing.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/blessing_of_leeches.txt svneol=native#text/plain
|
res/cardsfolder/blessing_of_leeches.txt svneol=native#text/plain
|
||||||
@@ -3733,6 +3734,7 @@ res/cardsfolder/mageta_the_lion.txt -text svneol=native#text/plain
|
|||||||
res/cardsfolder/magetas_boon.txt -text svneol=native#text/plain
|
res/cardsfolder/magetas_boon.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/maggot_carrier.txt -text svneol=native#text/plain
|
res/cardsfolder/maggot_carrier.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/maggot_therapy.txt -text svneol=native#text/plain
|
res/cardsfolder/maggot_therapy.txt -text svneol=native#text/plain
|
||||||
|
res/cardsfolder/magister_sphinx.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/magistrates_scepter.txt -text svneol=native#text/plain
|
res/cardsfolder/magistrates_scepter.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/magistrates_veto.txt -text svneol=native#text/plain
|
res/cardsfolder/magistrates_veto.txt -text svneol=native#text/plain
|
||||||
res/cardsfolder/magma_giant.txt -text svneol=native#text/plain
|
res/cardsfolder/magma_giant.txt -text svneol=native#text/plain
|
||||||
|
|||||||
8
res/cardsfolder/blessed_wind.txt
Normal file
8
res/cardsfolder/blessed_wind.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Blessed Wind
|
||||||
|
ManaCost:7 W W
|
||||||
|
Types:Sorcery
|
||||||
|
Text:no text
|
||||||
|
A:SP$SetLife | Cost$ 7 W W | ValidTgts$ Player | TgtPrompt$ Select target player | LifeAmount$ 20 | SpellDescription$ Target player's life total becomes 20.
|
||||||
|
SVar:Rarity:Rare
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/blessed_wind.jpg
|
||||||
|
End
|
||||||
11
res/cardsfolder/magister_sphinx.txt
Normal file
11
res/cardsfolder/magister_sphinx.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Name:Magister Sphinx
|
||||||
|
ManaCost:4 W U B
|
||||||
|
Types:Artifact Creature Sphinx
|
||||||
|
Text:no text
|
||||||
|
PT:5/5
|
||||||
|
K:Flying
|
||||||
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigLife | TriggerDescription$ When CARDNAME enters the battlefield, target player's life total becomes 10.
|
||||||
|
SVar:TrigLife:AB$SetLife | Cost$ 0 | ValidTgts$ Player | TgtPrompt$ Select target player | LifeAmount$ 10
|
||||||
|
SVar:Rarity:Rare
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/magister_sphinx.jpg
|
||||||
|
End
|
||||||
@@ -339,6 +339,15 @@ public class AbilityFactory {
|
|||||||
SA = AbilityFactory_AlterLife.createDrawbackLoseLife(this);
|
SA = AbilityFactory_AlterLife.createDrawbackLoseLife(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (API.equals("SetLife")){
|
||||||
|
if (isAb)
|
||||||
|
SA = AbilityFactory_AlterLife.createAbilitySetLife(this);
|
||||||
|
else if (isSp)
|
||||||
|
SA = AbilityFactory_AlterLife.createSpellSetLife(this);
|
||||||
|
else if (isDb)
|
||||||
|
SA = AbilityFactory_AlterLife.createDrawbackSetLife(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (API.equals("Poison")){
|
if (API.equals("Poison")){
|
||||||
if (isAb)
|
if (isAb)
|
||||||
SA = AbilityFactory_AlterLife.createAbilityPoison(this);
|
SA = AbilityFactory_AlterLife.createAbilityPoison(this);
|
||||||
|
|||||||
@@ -742,4 +742,255 @@ public class AbilityFactory_AlterLife {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// *************************************************************************
|
||||||
|
// ************************** SET LIFE *************************************
|
||||||
|
// *************************************************************************
|
||||||
|
|
||||||
|
public static SpellAbility createAbilitySetLife(final AbilityFactory AF) {
|
||||||
|
final SpellAbility abSetLife = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = -7375434097541097668L;
|
||||||
|
final AbilityFactory af = AF;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return setLifeStackDescription(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlayAI() {
|
||||||
|
return setLifeCanPlayAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
setLifeResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTrigger(boolean mandatory) {
|
||||||
|
return setLifeDoTriggerAI(af, this, mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return abSetLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpellAbility createSpellSetLife(final AbilityFactory AF) {
|
||||||
|
final SpellAbility spSetLife = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = -94657822256270222L;
|
||||||
|
final AbilityFactory af = AF;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return setLifeStackDescription(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlayAI() {
|
||||||
|
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
|
||||||
|
// then call xCount with that card to properly calculate the amount
|
||||||
|
// Or choosing how many to sacrifice
|
||||||
|
return setLifeCanPlayAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
setLifeResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return spSetLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpellAbility createDrawbackSetLife(final AbilityFactory AF) {
|
||||||
|
final SpellAbility dbSetLife = new Ability_Sub(AF.getHostCard(), AF.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = -7634729949893534023L;
|
||||||
|
final AbilityFactory af = AF;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return setLifeStackDescription(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlayAI() {
|
||||||
|
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
|
||||||
|
// then call xCount with that card to properly calculate the amount
|
||||||
|
// Or choosing how many to sacrifice
|
||||||
|
return setLifeCanPlayAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
setLifeResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chkAI_Drawback() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTrigger(boolean mandatory) {
|
||||||
|
return setLifeDoTriggerAI(af, this, mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return dbSetLife;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String setLifeStackDescription(AbilityFactory af, SpellAbility sa) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int amount = AbilityFactory.calculateAmount(af.getHostCard(), af.getMapParams().get("LifeAmount"), sa);
|
||||||
|
|
||||||
|
if (!(sa instanceof Ability_Sub))
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" -");
|
||||||
|
|
||||||
|
sb.append(" ");
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
Target tgt = af.getAbTgt();
|
||||||
|
if(tgt != null)
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
else
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), af.getMapParams().get("Defined"), sa);
|
||||||
|
|
||||||
|
for(Player player : tgtPlayers)
|
||||||
|
sb.append(player).append(" ");
|
||||||
|
|
||||||
|
sb.append("life total becomes ").append(amount).append(".");
|
||||||
|
|
||||||
|
Ability_Sub abSub = sa.getSubAbility();
|
||||||
|
if(abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean setLifeCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
Random r = new Random();
|
||||||
|
//Ability_Cost abCost = sa.getPayCosts();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
int life = AllZone.ComputerPlayer.getLife();
|
||||||
|
int hlife = AllZone.HumanPlayer.getLife();
|
||||||
|
String amountStr = af.getMapParams().get("LifeAmount");
|
||||||
|
|
||||||
|
if(!ComputerUtil.canPayCost(sa))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!AllZone.ComputerPlayer.canGainLife())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO handle proper calculation of X values based on Cost and what would be paid
|
||||||
|
int amount;
|
||||||
|
//we shouldn't have to worry too much about PayX for SetLife
|
||||||
|
if(amountStr.equals("X") && source.getSVar(amountStr).equals("Count$xPaid")) {
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
int xPay = ComputerUtil.determineLeftoverMana(sa);
|
||||||
|
source.setSVar("PayX", Integer.toString(xPay));
|
||||||
|
amount = xPay;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
|
||||||
|
|
||||||
|
// prevent run-away activations - first time will always return true
|
||||||
|
boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());
|
||||||
|
|
||||||
|
Target tgt = sa.getTarget();
|
||||||
|
if(tgt != null){
|
||||||
|
tgt.resetTargets();
|
||||||
|
if(tgt.canOnlyTgtOpponent()) {
|
||||||
|
tgt.addTarget(AllZone.HumanPlayer);
|
||||||
|
//if we can only target the human, and the Human's life would go up, don't play it.
|
||||||
|
//possibly add a combo here for Magister Sphinx and Higedetsu's (sp?) Second Rite
|
||||||
|
if(amount > hlife || !AllZone.HumanPlayer.canLoseLife()) return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(amount > life && life <= 10) tgt.addTarget(AllZone.ComputerPlayer);
|
||||||
|
else if(hlife > amount) tgt.addTarget(AllZone.HumanPlayer);
|
||||||
|
else if(amount > life) tgt.addTarget(AllZone.ComputerPlayer);
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(amount < life) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if life is in danger, always activate
|
||||||
|
if(life < 3 && amount > life) return true;
|
||||||
|
|
||||||
|
return ((r.nextFloat() < .6667) && chance);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean setLifeDoTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory){
|
||||||
|
int life = AllZone.ComputerPlayer.getLife();
|
||||||
|
int hlife = AllZone.HumanPlayer.getLife();
|
||||||
|
Card source = sa.getSourceCard();
|
||||||
|
String amountStr = af.getMapParams().get("LifeAmount");
|
||||||
|
if (!ComputerUtil.canPayCost(sa) && !mandatory) // If there is a cost payment it's usually not mandatory
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int amount;
|
||||||
|
if (amountStr.equals("X") && source.getSVar(amountStr).equals("Count$xPaid")){
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
int xPay = ComputerUtil.determineLeftoverMana(sa);
|
||||||
|
source.setSVar("PayX", Integer.toString(xPay));
|
||||||
|
amount = xPay;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
|
||||||
|
|
||||||
|
// If the Target is gaining life, target self.
|
||||||
|
// if the Target is modifying how much life is gained, this needs to be handled better
|
||||||
|
Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null){
|
||||||
|
tgt.resetTargets();
|
||||||
|
if (tgt.canOnlyTgtOpponent())
|
||||||
|
tgt.addTarget(AllZone.HumanPlayer);
|
||||||
|
else {
|
||||||
|
if(amount > life && life <= 10) tgt.addTarget(AllZone.ComputerPlayer);
|
||||||
|
else if(hlife > amount) tgt.addTarget(AllZone.HumanPlayer);
|
||||||
|
else if(amount > life) tgt.addTarget(AllZone.ComputerPlayer);
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
Ability_Sub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setLifeResolve(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
HashMap<String,String> params = af.getMapParams();
|
||||||
|
Card card = af.getHostCard();
|
||||||
|
int lifeAmount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), sa);
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
Target tgt = af.getAbTgt();
|
||||||
|
if(tgt != null && !params.containsKey("Defined"))
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
else
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
|
||||||
|
for(Player p : tgtPlayers)
|
||||||
|
if(tgt == null || p.canTarget(af.getHostCard()))
|
||||||
|
p.setLife(lifeAmount, sa.getSourceCard());
|
||||||
|
|
||||||
|
if(af.hasSubAbility()) {
|
||||||
|
Ability_Sub abSub = sa.getSubAbility();
|
||||||
|
if(abSub != null) {
|
||||||
|
abSub.resolve();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String DrawBack = params.get("SubAbility");
|
||||||
|
if(af.hasSubAbility())
|
||||||
|
CardFactoryUtil.doDrawBack(DrawBack, lifeAmount, card.getController(), card.getController().getOpponent(), tgtPlayers.get(0), card, null, sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end class AbilityFactory_AlterLife
|
||||||
|
|||||||
Reference in New Issue
Block a user