mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18: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/blessed_orator.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/blessing.txt -text 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/maggot_carrier.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_veto.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);
|
||||
}
|
||||
|
||||
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 (isAb)
|
||||
SA = AbilityFactory_AlterLife.createAbilityPoison(this);
|
||||
|
||||
@@ -742,4 +742,255 @@ public class AbilityFactory_AlterLife {
|
||||
|
||||
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