package com.planet_ink.coffee_mud.Commands;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.Session.InputCallback;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.AchievementLibrary.Event;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;
import java.io.IOException;
import java.util.*;
/*
Copyright 2015-2016 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
public class Remort extends StdCommand
{
public Remort()
{
}
private final String[] access = I(new String[] { "REMORT" });
@Override
public String[] getAccessWords()
{
return access;
}
private enum RemortRetain
{
HITPOINT,
MANA,
MOVE,
LEVEL,
ATTACK,
DEFENSE,
SKILL,
SKILLSAT100,
FACTION,
EXPERTISE,
BONUSSTATPOINT,
QUESTPOINT
}
private static void recoverEverything(final MOB mob)
{
mob.recoverCharStats();
mob.recoverMaxState();
mob.resetToMaxState();
mob.recoverPhyStats();
}
@Override
public boolean execute(final MOB mob, List<String> commands, int metaFlags)
throws java.io.IOException
{
final Session session=mob.session();
if(session==null)
return false;
final PlayerStats pstats=mob.playerStats();
if(pstats==null)
return false;
if(!CMLib.masking().maskCheck(CMProps.getVar(CMProps.Str.REMORTMASK), mob, true))
{
mob.tell(L("You do not meet the requirements to re-mortalize at this time."));
mob.tell(L("The requirements are: @x1",CMLib.masking().maskDesc(CMProps.getVar(CMProps.Str.REMORTMASK))));
return false;
}
final int[] newLevel = new int[]{1};
final int[] newMana = new int[]{CMProps.getIntVar(CMProps.Int.STARTMANA)};
final int[] newHp = new int[]{CMProps.getIntVar(CMProps.Int.STARTHP)};
final int[] newMove = new int[]{CMProps.getIntVar(CMProps.Int.STARTMOVE)};
final int[] newAttack = new int[]{0};
final int[] newDefense = new int[]{100};
final int[] bonusPointsPerStat = new int[]{0};
final int[] questPoint = new int[]{0};
final List<Pair<String,Integer>> factions=new ArrayList<Pair<String,Integer>>();
final List<Triad<String,String,Integer>> abilities=new ArrayList<Triad<String,String,Integer>>();
final List<Triad<String,String,Integer>> abilities100=new ArrayList<Triad<String,String,Integer>>();
final List<String> expertises=new ArrayList<String>();
for(String thing : CMParms.parseCommas(CMProps.getVar(CMProps.Str.REMORTRETAIN), true))
{
thing=thing.toUpperCase().trim();
RemortRetain retainer = (RemortRetain)CMath.s_valueOf(RemortRetain.class, thing);
String rest="";
if(retainer == null)
{
for(RemortRetain r : RemortRetain.values())
{
if(thing.endsWith(r.name()))
{
retainer = r;
rest = thing.substring(0,thing.length()-r.name().length()).trim();
}
else
if(thing.endsWith(r.name()+"S"))
{
retainer = r;
rest = thing.substring(0,thing.length()-r.name().length()-1).trim();
}
else
if(thing.startsWith(r.name()))
{
retainer = r;
rest = thing.substring(r.name().length()).trim();
}
else
if(thing.startsWith(r.name()+"S"))
{
retainer = r;
rest = thing.substring(r.name().length()+1).trim();
}
}
}
if(retainer != null)
{
int flatAmount=0;
double pctAmount = 1.0;
if(CMath.isPct(rest))
{
pctAmount = CMath.s_pct(rest);
}
else
if(CMath.isInteger(rest))
{
flatAmount = CMath.s_int(rest);
}
else
if(CMath.isNumber(rest))
{
double d=CMath.s_double(rest);
if((d>0.0)&&(d<1.0))
pctAmount = d;
else
pctAmount = d/100.0;
}
switch(retainer)
{
case ATTACK:
{
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, mob.basePhyStats().attackAdjustment()));
total += flatAmount;
newAttack[0] += total;
break;
}
case QUESTPOINT:
{
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, mob.getQuestPoint()));
total += flatAmount;
questPoint[0] += total;
break;
}
case DEFENSE:
{
int total = 0;
if(pctAmount != 0)
{
int armorDiff = 0;
if(mob.basePhyStats().armor() < 0)
armorDiff = (-mob.basePhyStats().armor()) + 100;
else
armorDiff = 100 - mob.basePhyStats().armor();
total -= (int)Math.round(CMath.mul(pctAmount, armorDiff));
}
total -= flatAmount;
newDefense[0] += total;
break;
}
case HITPOINT:
{
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, mob.baseState().getHitPoints())) - CMProps.getIntVar(CMProps.Int.STARTHP);
total += flatAmount;
newHp[0] += total;
break;
}
case LEVEL:
{
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, mob.basePhyStats().level())) - 1;
total += flatAmount;
if(total > 1)
newLevel[0] = total;
break;
}
case MANA:
{
int total = 0;
if(pctAmount != 0)
total = (int)Math.round(CMath.mul(pctAmount, mob.baseState().getMana())) - CMProps.getIntVar(CMProps.Int.STARTMANA);
total += flatAmount;
newMana[0] += total;
break;
}
case MOVE:
{
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, mob.baseState().getMovement())) - CMProps.getIntVar(CMProps.Int.STARTMOVE);
total += flatAmount;
newMove[0] += total;
break;
}
case SKILL:
{
for(Enumeration<Ability> a=mob.abilities();a.hasMoreElements();)
{
Ability A=a.nextElement();
abilities.add(new Triad<String,String,Integer>(A.ID(),A.text(),new Integer(A.proficiency())));
}
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, abilities.size()));
total += flatAmount;
while(abilities.size()>total)
abilities.remove(CMLib.dice().roll(1, abilities.size(), -1));
break;
}
case SKILLSAT100:
{
for(Enumeration<Ability> a=mob.abilities();a.hasMoreElements();)
{
Ability A=a.nextElement();
if(A.proficiency() >= 100)
abilities100.add(new Triad<String,String,Integer>(A.ID(),A.text(),new Integer(A.proficiency())));
}
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, abilities.size()));
total += flatAmount;
while(abilities100.size()>total)
abilities100.remove(CMLib.dice().roll(1, abilities100.size(), -1));
break;
}
case FACTION:
{
for(Enumeration<String> f = mob.factions();f.hasMoreElements();)
{
String facID = f.nextElement();
factions.add(new Pair<String,Integer>(facID,new Integer(mob.fetchFaction(facID))));
}
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, factions.size()));
total += flatAmount;
while(factions.size()>total)
factions.remove(CMLib.dice().roll(1, factions.size(), -1));
break;
}
case EXPERTISE:
{
for(Enumeration<String> f = mob.expertises();f.hasMoreElements();)
{
String expID = f.nextElement();
expertises.add(expID);
}
int total = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, expertises.size()));
total += flatAmount;
while(expertises.size()>total)
expertises.remove(CMLib.dice().roll(1, expertises.size(), -1));
break;
}
case BONUSSTATPOINT:
{
int total = 0;
int totalnow = 0;
for(int stat : CharStats.CODES.BASECODES())
totalnow += mob.baseCharStats().getStat(stat);
int startStat=CMProps.getIntVar(CMProps.Int.STARTSTAT);
if((CMSecurity.isDisabled(CMSecurity.DisFlag.ATTRIBS)&&(startStat<=0)))
totalnow -= (10 * CharStats.CODES.BASECODES().length);
else
{
totalnow -= CMProps.getIntVar(CMProps.Int.BASEMINSTAT) * CharStats.CODES.BASECODES().length;
totalnow -= CMLib.login().getTotalBonusStatPoints(pstats, pstats.getAccount());
}
if(totalnow < 0)
totalnow = 0;
if(pctAmount != 0)
total += (int)Math.round(CMath.mul(pctAmount, totalnow));
total += flatAmount;
bonusPointsPerStat[0] += total;
break;
}
}
}
}
mob.tell(L("^HThis will drop your level back to @x1!",""+newLevel[0]));
session.prompt(new InputCallback(InputCallback.Type.PROMPT,"",120000)
{
@Override
public void showPrompt()
{
session.promptPrint(L("If that's what you want, re-enter your password: "));
}
@Override
public void timedOut()
{
}
@Override
public void callBack()
{
if(input.trim().length()==0)
return;
if(!pstats.matchesPassword(input.trim()))
mob.tell(L("Password incorrect."));
else
{
Log.sysOut("Retire","Remort: "+mob.Name());
CMLib.achievements().possiblyBumpAchievement(mob, Event.REMORT, 1);
mob.basePhyStats().setLevel(1);
mob.basePhyStats().setArmor(newDefense[0]);
mob.basePhyStats().setAttackAdjustment(newAttack[0]);
mob.basePhyStats().setSpeed(1.0);
mob.baseState().setHitPoints(newHp[0]);
mob.baseState().setMana(newMana[0]);
mob.baseState().setMovement(newMove[0]);
mob.delAllAbilities();
mob.delAllBehaviors();
mob.delAllScripts();
mob.delAllExpertises();
mob.setExperience(0);
for(Triad<String,String,Integer> PA : abilities)
{
Ability A=CMClass.getAbility(PA.first);
if(A!=null)
{
A.setMiscText(A.text());
A.setProficiency(0);
mob.addAbility(A);
}
}
for(Triad<String,String,Integer> PA : abilities100)
{
Ability A=CMClass.getAbility(PA.first);
if(A!=null)
{
A.setMiscText(A.text());
A.setProficiency(100);
mob.addAbility(A);
}
}
for(Pair<String,Integer> PA : factions)
{
mob.addFaction(PA.first, PA.second.intValue());
}
for(String PA : expertises)
{
mob.addExpertise(PA);
}
mob.setStartRoom(CMLib.login().getDefaultStartRoom(mob));
mob.getStartRoom().bringMobHere(mob, true);
final String failsafeID = "RemoteFailSafe";
MsgListener finishRemoteListener = new MsgListener()
{
final MsgListener me=this;
@Override
public void executeMsg(Environmental myHost, CMMsg msg)
{
if((msg.source() == myHost)
&&(myHost instanceof MOB)
&&(msg.sourceMinor()==CMMsg.TYP_LIFE))
{
Runnable remortRun = new Runnable()
{
@Override
public void run()
{
try
{
final Session sess = mob.session();
mob.baseCharStats().setMyClasses("StdCharClass");
mob.baseCharStats().setMyLevels("1");
mob.basePhyStats().setLevel(1);
for (final Enumeration<Ability> a = mob.personalEffects(); a.hasMoreElements();)
{
final Ability A = a.nextElement();
if ((A != null)&& (A.canBeUninvoked()))
{
A.unInvoke();
mob.delEffect(A);
}
}
Ability oldFailSafeA=mob.fetchEffect(failsafeID);
if(oldFailSafeA!=null)
mob.delEffect(oldFailSafeA);
ExtendableAbility failsafeA=(ExtendableAbility)CMClass.getAbility("ExtAbility");
if(failsafeA!=null)
{
failsafeA.setAbilityID(failsafeID);
failsafeA.setMsgListener(me);
failsafeA.setSavable(false);
mob.addNonUninvokableEffect(failsafeA);
}
recoverEverything(mob);
CMLib.login().promptPlayerStats(mob.playerStats().getTheme(), mob, mob.session(), bonusPointsPerStat[0]);
if(sess.isStopped())
throw new IOException("Session stopped");
recoverEverything(mob);
mob.basePhyStats().setSensesMask(0);
mob.baseCharStats().getMyRace().startRacing(mob,false);
mob.setWimpHitPoint(5);
mob.setQuestPoint(questPoint[0]);
recoverEverything(mob);
mob.baseCharStats().setCurrentClass(CMLib.login().promptCharClass(mob.playerStats().getTheme(), mob, mob.session()));
if(sess.isStopped())
throw new IOException("Session stopped");
recoverEverything(mob);
mob.setPractices(0);
mob.setTrains(0);
mob.baseCharStats().getCurrentClass().startCharacter(mob, false, false);
mob.baseCharStats().getCurrentClass().grantAbilities(mob, false);
recoverEverything(mob);
recoverEverything(mob);
CMLib.achievements().loadAccountAchievements(mob);
CMLib.achievements().loadPlayerSkillAwards(mob, mob.playerStats());
CMLib.commands().postLook(mob, true);
if((!mob.charStats().getCurrentClass().leveless())
&&(!mob.charStats().isLevelCapped(mob.charStats().getCurrentClass()))
&&(!mob.charStats().getMyRace().leveless())
&&(!CMSecurity.isDisabled(CMSecurity.DisFlag.LEVELS)))
{
for(int i=1;i<newLevel[0];i++)
{
if((mob.getExpNeededLevel()==Integer.MAX_VALUE)
||(mob.charStats().getCurrentClass().expless())
||(mob.charStats().getMyRace().expless()))
CMLib.leveler().level(mob);
else
CMLib.leveler().postExperience(mob,null,null,mob.getExpNeededLevel()+1,false);
}
}
recoverEverything(mob);
CMLib.utensils().confirmWearability(mob);
recoverEverything(mob);
mob.tell(L("You have remorted back to level @x1!",""+mob.phyStats().level()));
Ability A=mob.fetchEffect(failsafeID);
if(A!=null)
mob.delEffect(A);
}
catch(java.lang.NullPointerException e)
{
}
catch (final IOException e)
{
}
}
};
if(msg.sourceMajor(CMMsg.MASK_CNTRLMSG))
remortRun.run();
else
CMLib.threads().scheduleRunnable(remortRun,500);
}
}
@Override
public boolean okMessage(Environmental myHost, CMMsg msg)
{
return true;
}
};
ExtendableAbility failsafeA=(ExtendableAbility)CMClass.getAbility("ExtAbility");
if(failsafeA!=null)
{
failsafeA.setAbilityID(failsafeID);
failsafeA.setMsgListener(finishRemoteListener);
failsafeA.setSavable(false);
mob.addNonUninvokableEffect(failsafeA);
}
finishRemoteListener.executeMsg(mob, CMClass.getMsg(mob, CMMsg.MSG_BRINGTOLIFE | CMMsg.MASK_CNTRLMSG, null));
}
}
});
return false;
}
@Override
public double combatActionsCost(final MOB mob, final List<String> cmds)
{
return CMProps.getCommandCombatActionCost(ID());
}
@Override
public double actionsCost(final MOB mob, final List<String> cmds)
{
return CMProps.getCommandActionCost(ID());
}
@Override
public boolean canBeOrdered()
{
return false;
}
}