package com.planet_ink.coffee_mud.Abilities.Misc; import com.planet_ink.coffee_mud.Abilities.StdAbility; 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.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Libraries.interfaces.*; 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.util.*; /* Copyright 2003-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 Pregnancy extends StdAbility implements HealthCondition { @Override public String ID() { return "Pregnancy"; } private final static String localizedName = CMLib.lang().L("Pregnancy"); @Override public String name() { return localizedName; } protected long monthsRemaining = -1; protected long daysRemaining = -1; @Override public String getHealthConditionDesc() { final int x=text().indexOf('/'); if(x>0) { final TimeClock C=CMLib.time().localClock(affected); final int y=text().indexOf('/',x+1); if(y<0) return ""; final long start=CMath.s_long(text().substring(0,x)); final long divisor=CMProps.getTickMillis()*CMProps.getIntVar(CMProps.Int.TICKSPERMUDDAY); final long days=(System.currentTimeMillis()-start)/divisor; // down to days; final long months=days/C.getDaysInMonth(); if(days<1) return "less than 1 day pregnant"; else if(months<1) return days+" day(s) pregnant"; else return months+" month(s) pregnant"; } return ""; } @Override public String displayText() { final String text=getHealthConditionDesc(); if(text.length()>0) return "(is "+text+")"; return ""; } @Override protected int canAffectCode() { return CAN_MOBS; } @Override protected int canTargetCode() { return CAN_MOBS; } @Override public int abstractQuality() { return Ability.QUALITY_INDIFFERENT; } @Override public boolean putInCommandlist() { return false; } private static final String[] triggerStrings = I(new String[] { "IMPREGNATE" }); @Override public String[] triggerStrings() { return triggerStrings; } @Override public boolean canBeUninvoked() { return false; } @Override public boolean isAutoInvoked() { return false; } @Override public boolean isSavable() { return true; } @Override public int classificationCode() { return Ability.ACODE_PROPERTY; } protected int ticksInLabor = 0; @Override public void executeMsg(Environmental host, CMMsg msg) { if((msg.target()==affected) &&((msg.targetMinor()==CMMsg.TYP_LOOK)||(msg.targetMinor()==CMMsg.TYP_EXAMINE)) &&(CMLib.flags().canBeSeenBy(affected,msg.source())) &&(affected instanceof MOB) &&((daysRemaining>0)&&(monthsRemaining<=3))) { msg.addTrailerMsg(CMClass.getMsg(msg.source(),null,null, CMMsg.MSG_OK_VISUAL,L("\n\r<S-NAME> <S-IS-ARE> obviously with child.\n\r"), CMMsg.NO_EFFECT,null, CMMsg.NO_EFFECT,null)); } super.executeMsg(host,msg); } public Race getRace(MOB babe, String race1, String race2) { if(race1.indexOf(race2)>=0) return CMClass.getRace(race1); else if(race2.indexOf(race1)>=0) return CMClass.getRace(race2); Race R=null; if(race1.equalsIgnoreCase("Human")||race2.equalsIgnoreCase("Human")) { String halfRace=(race1.equalsIgnoreCase("Human")?race2:race1); R=CMClass.getRace(halfRace); if((R!=null)&&(!R.ID().toUpperCase().startsWith("HALF"))) { halfRace="Half"+CMStrings.capitalizeAndLower(R.ID().toLowerCase()); final Race testR=CMClass.getRace(halfRace); if(testR!=null) R=testR; else { R=R.mixRace(CMClass.getRace("Human"),halfRace,"Half "+CMStrings.capitalizeAndLower(R.name())); if(R.isGeneric() && (!R.ID().equals(race1))&& (!R.ID().equals(race2))) { CMClass.addRace(R); CMLib.database().DBCreateRace(R.ID(),R.racialParms()); } } } } else if(race1.equalsIgnoreCase("Halfling")||race2.equalsIgnoreCase("Halfling")) { String halfRace=(race1.equalsIgnoreCase("Halfling")?race2:race1); R=CMClass.getRace(halfRace); if((R!=null)&&(!R.ID().endsWith("ling"))) { halfRace=R.ID()+"ling"; final Race testR=CMClass.getRace(halfRace); if(testR!=null) R=testR; else { R=R.mixRace(CMClass.getRace("Halfling"),halfRace,CMStrings.capitalizeAndLower(R.name())+"ling"); if(R.isGeneric() && (!R.ID().equals(race1))&& (!R.ID().equals(race2))) { CMClass.addRace(R); CMLib.database().DBCreateRace(R.ID(),R.racialParms()); } } } } else { String first=null; if(race1.length()==race2.length()) first=(race1.compareToIgnoreCase(race2)<0)?race1:race2; else if(race1.length()>race2.length()) first=race1; else first=race2; final String second=(first.equals(race1)?race2:race1); final String halfRace=(race1.compareToIgnoreCase(race2)<0)?race1+race2:race2+race1; final Race testR=CMClass.getRace(halfRace); final Race FIRSTR=CMClass.getRace(first); final Race SECONDR=CMClass.getRace(second); if(testR!=null) R=testR; else { R=FIRSTR.mixRace(SECONDR,halfRace,FIRSTR.name()+"-"+SECONDR.name()); if(R.isGeneric() && (!R.ID().equals(race1))&& (!R.ID().equals(race2))) { CMClass.addRace(R); CMLib.database().DBCreateRace(R.ID(),R.racialParms()); } } } return R; } @Override public boolean tick(Tickable ticking, int tickID) { if(!super.tick(ticking,tickID)) return false; if((tickID==Tickable.TICKID_MOB) &&(affected instanceof MOB) &&(CMLib.flags().isInTheGame((MOB)affected,true))) { final MOB mob=(MOB)affected; final int x=text().indexOf('/'); if(x>0) { final int y=text().indexOf('/',x+1); if(y>x) { final TimeClock C=CMLib.time().localClock(mob.getStartRoom()); final int z=text().indexOf('/',y+1); final long end=CMath.s_long(text().substring(x+1,y)); final long divisor=CMProps.getTickMillis()*CMProps.getIntVar(CMProps.Int.TICKSPERMUDDAY); daysRemaining=(end-System.currentTimeMillis())/divisor; // down to days monthsRemaining=daysRemaining/C.getDaysInMonth(); // down to months if(CMLib.dice().roll(1,200,0)==1) { final Ability A=CMClass.getAbility("Mood"); if(A!=null) A.invoke(mob,new XVector<String>("RANDOM"),mob,true,0); } if(daysRemaining<7) // BIRTH! { if(CMLib.flags().isSleeping(mob)) mob.enqueCommand(CMParms.parse("WAKE"),MUDCmdProcessor.METAFLAG_FORCED,0); if((CMLib.dice().rollPercentage()>50)&&(mob.charStats().getStat(CharStats.STAT_INTELLIGENCE)>5)) mob.location().show(mob,null,CMMsg.MSG_NOISE,L("<S-NAME> moan(s) and scream(s) in labor pain!!")); ticksInLabor++; if(ticksInLabor>=45) { ticksInLabor=0; final String race1=mob.baseCharStats().getMyRace().ID(); char gender='F'; String sondat="daughter"; final MOB babe=CMClass.getMOB("GenMOB"); if(CMLib.dice().rollPercentage()>50) { gender='M'; sondat="son"; } String desc="The "+sondat+" of "+mob.Name(); babe.addTattoo("PARENT:"+mob.Name()); String race2=mob.baseCharStats().getMyRace().ID(); MOB otherParentM=null; if(z>y) { race2=text().substring(z+1).trim(); otherParentM=CMLib.players().getLoadPlayer(text().substring(y+1,z)); desc+=" and "+text().substring(y+1,z); if(otherParentM != null) { babe.addTattoo("PARENT:"+otherParentM.Name()); } } desc+="."; mob.curState().setMovement(0); mob.curState().setHitPoints(mob.curState().getHitPoints()/2); mob.location().show(mob,null,CMMsg.MSG_NOISE,L("***** <S-NAME> !!!GIVE(S) BIRTH!!! ******")); if(CMLib.dice().rollPercentage()>5) { Ability A=mob.fetchEffect(ID()); while(A!=null) { mob.delEffect(A); A.setAffectedOne(null); A=mob.fetchEffect(ID()); } A=mob.fetchAbility(ID()); while(A!=null) { mob.delAbility(A); A.setAffectedOne(null); A=mob.fetchAbility(ID()); } } Race R=getRace(babe,race1,race2); if(R==null) R=mob.baseCharStats().getMyRace(); String name=CMLib.english().startWithAorAn(R.makeMobName(gender, 2)).toLowerCase(); babe.setName(name); CMLib.factions().setAlignment(babe,Faction.Align.GOOD); for(final Pair<Clan,Integer> p : CMLib.clans().findRivalrousClans(mob)) babe.setClan(p.first.clanID(),p.first.getAutoPosition()); babe.setLiegeID(mob.getLiegeID()); babe.setDescription(desc); babe.setDisplayText(L("@x1 is here.",name)); CMLib.beanCounter().clearZeroMoney(babe,null); babe.baseCharStats().setMyRace(R); babe.baseCharStats().setStat(CharStats.STAT_CHARISMA,10); babe.baseCharStats().setStat(CharStats.STAT_CONSTITUTION,6); babe.baseCharStats().setStat(CharStats.STAT_DEXTERITY,2); babe.baseCharStats().setStat(CharStats.STAT_GENDER,gender); babe.baseCharStats().setStat(CharStats.STAT_INTELLIGENCE,2); babe.baseCharStats().setStat(CharStats.STAT_STRENGTH,1); babe.baseCharStats().setStat(CharStats.STAT_WISDOM,1); babe.baseCharStats().getMyRace().startRacing(babe,false); babe.basePhyStats().setHeight(babe.basePhyStats().height()/10); babe.basePhyStats().setWeight(babe.basePhyStats().weight()/10); babe.baseState().setHitPoints(1); babe.baseState().setMana(0); babe.baseState().setMovement(0); babe.recoverCharStats(); if(!CMLib.flags().isAnimalIntelligence(babe)) { if(CMLib.dice().rollPercentage()>50) { Ability A=mob.fetchEffect("Allergies"); if(A!=null) { A=(Ability)A.copyOf(); babe.addNonUninvokableEffect(A); } else { A=CMClass.getAbility("Allergies"); if(A!=null) A.invoke(babe,babe,true,0); } } final Ability STAT=CMClass.getAbility("Prop_StatTrainer"); if(STAT!=null) { STAT.setMiscText("CHA=10 CON=6 DEX=2 INT=2 STR=1 WIS=1"); babe.addNonUninvokableEffect(STAT); } } final Ability SAFE=CMClass.getAbility("Prop_SafePet"); if(SAFE!=null) babe.addNonUninvokableEffect(SAFE); final Ability AGE=CMClass.getAbility("Age"); if(AGE!=null) { AGE.setMiscText(""+System.currentTimeMillis()); babe.addNonUninvokableEffect(AGE); } babe.recoverCharStats(); babe.recoverPhyStats(); babe.recoverMaxState(); babe.resetToMaxState(); final Item I=CMClass.getItem("GenCaged"); ((CagedAnimal)I).cageMe(babe); ((CagedAnimal)I).setCageFlagsBitmap(CagedAnimal.CAGEFLAG_TO_MOB_PROGRAMMATICALLY); if(AGE != null) I.addNonUninvokableEffect((Ability)AGE.copyOf()); name=CMLib.english().startWithAorAn(R.makeMobName((char)babe.baseCharStats().getStat(CharStats.STAT_GENDER), 1)).toLowerCase(); I.setName(name); I.setDisplayText(L("@x1 is here.",name)); I.recoverPhyStats(); mob.location().addItem(I); final Behavior B=CMClass.getBehavior("Emoter"); B.setParms(Age.happyBabyEmoter); I.addBehavior(B); I.text(); if((!mob.isMonster())&&(mob.soulMate()==null)) { if((CMLib.dice().rollPercentage()<20)&&(mob.fetchEffect("Disease_Depression")==null)) { final Ability A=CMClass.getAbility("Disease_Depression"); if(A!=null) A.invoke(mob,mob,true,0); } } if((mob.playerStats()!=null)||((otherParentM!=null)&&(otherParentM.playerStats()!=null))) { CMLib.coffeeTables().bump(mob,CoffeeTableRow.STAT_BIRTHS); final List<String> channels=CMLib.channels().getFlaggedChannelNames(ChannelsLibrary.ChannelFlag.BIRTHS); for(int i=0;i<channels.size();i++) CMLib.commands().postChannel(mob,channels.get(i),L("@x1 has just given birth to @x2!",mob.name(),I.name()),true); String parent=mob.Name(); if(mob.isMonster()&&(otherParentM!=null)) parent=otherParentM.Name(); if(AGE!=null) CMLib.database().DBCreateData(parent,"HEAVEN",parent+"/HEAVEN/"+AGE.text(),I.ID()+"/"+I.basePhyStats().ability()+"/"+I.text()); } } else mob.tell(L("You are in labor!!")); } else { // pregnant folk get fatigued more often. if(mob.maxState().getFatigue()>Long.MIN_VALUE/2) mob.curState().adjFatigue(monthsRemaining*100,mob.maxState()); if((monthsRemaining<=1)&&(CMLib.dice().rollPercentage()==1)) { if(CMLib.flags().isSleeping(mob)) mob.enqueCommand(CMParms.parse("WAKE"),MUDCmdProcessor.METAFLAG_FORCED,0); mob.tell(L("Oh! You had a contraction!")); } else if((monthsRemaining<=3)&&(CMLib.dice().rollPercentage()==1)&&(CMLib.dice().rollPercentage()==1)) mob.tell(L("You feel a kick in your gut.")); else if((monthsRemaining>8)&&(mob.location()!=null)&&(mob.location().getArea().getTimeObj().getHourOfDay()<2)&&(CMLib.dice().rollPercentage()==1)) { if(CMLib.dice().rollPercentage()>25) mob.tell(L("You feel really sick this morning.")); else mob.location().show(mob,null,CMMsg.MSG_NOISYMOVEMENT,L("**BLEH** <S-NAME> just threw up.")); } } } } } return true; } @Override public boolean invoke(MOB mob, List<String> commands, Physical givenTarget, boolean auto, int asLevel) { final MOB target=getTarget(mob,commands,givenTarget); if(target==null) return false; if(!super.invoke(mob,commands,givenTarget,auto,asLevel)) return false; final boolean success=proficiencyCheck(mob,0,auto); long start=System.currentTimeMillis(); final Race R=target.charStats().getMyRace(); long tickspermudmonth=CMProps.getIntVar(CMProps.Int.TICKSPERMUDDAY); final TimeClock C=CMLib.time().localClock(target.getStartRoom()); tickspermudmonth=tickspermudmonth*C.getDaysInMonth(); int birthmonths=(int)Math.round(CMath.mul((R.getAgingChart()[1]-R.getAgingChart()[0])*C.getMonthsInYear(),0.75)); if(birthmonths<=0) birthmonths=5; final long ticksperbirthperiod=tickspermudmonth*birthmonths; final long millisperbirthperiod=ticksperbirthperiod*CMProps.getTickMillis(); long end=start+millisperbirthperiod; if(success) { if(!auto) { end=start; start-=millisperbirthperiod; } if(mob.location().show(mob,target,this,CMMsg.TYP_GENERAL,auto?null:L("<S-NAME> imgregnate(s) <T-NAMESELF>."))) { setMiscText(start+"/"+end+"/"+mob.Name()+"/"+mob.charStats().getMyRace().ID()); final List<String> channels=CMLib.channels().getFlaggedChannelNames(ChannelsLibrary.ChannelFlag.CONCEPTIONS); for(int i=0;i<channels.size();i++) CMLib.commands().postChannel(channels.get(i),mob.clans(),L("@x1 is now in a 'family way'.",target.name()),true); target.addNonUninvokableEffect((Ability)copyOf()); } } else if(!auto) return beneficialVisualFizzle(mob,target,L("<S-NAME> attempt(s) to impregnate <T-NAMESELF>, but fail(s)!")); return success; } }