Fixed a bunch of stupid problems.
[18plus-7leafadventure.git] / src / org / sevenchan / dongs / Creature.as
blob4203923831e4f89c3e8fe9ab65435c0dc914b582
1 package org.sevenchan.dongs
3 import flash.net.*;
4 import org.sevenchan.AdventureController;
5 import org.sevenchan.dongs.bodyparts.*;
6 import org.sevenchan.dongs.clothing.Clothing;
7 import org.sevenchan.dongs.clothing.ClothingType;
8 import org.sevenchan.dongs.creature.*;
9 import org.sevenchan.dongs.enchantment.*;
10 import org.sevenchan.dongs.enchantment.events.*;
11 import org.sevenchan.dongs.screens.*;
12 import org.sevenchan.dongs.weapons.IWeapon;
14 /**
15 * It's alive!
16 * @author Harbinger
18 public class Creature
20 registerClassAlias("ECreature", Creature);
22 // Characteristics
23 public var customized:Boolean = false;
24 public var ownName:String = "Blah Blah"; // Who am I?
25 public var height:Number = 0.0; // How tall am I?
26 public var build:Build = Build.AVG; // How fat am I?
27 public var material:Material = Material.NO_MATERIAL_MODIFIER; // What am I made of?
28 public var hair:Hair = Hair.BALD; // His/her/hir hair is...
29 public var skin:Skin = new Skin("human"); // His/her/hir hair is...
30 public var _gender:Gender = Gender.ASEXUAL; // Boy, Girl, Neither, Both?
31 public var sexualPreference:SexualPreference = SexualPreference.ASEXUAL; // Straight, Gay, ASexual, Bi?
33 private var mGenderInitialized:Boolean = false;
35 // Stats (CACHED VALUES)
36 public var _level:int = 0; // In comparison to standard human being. No attacking rats for 20 levels.
37 private var d_level:int = 0; // Delta
38 public var _strength:int = 1; // Damage caused in case of a successful attack.
39 public var _speed:int = 1; // Chance of dodging [0-1]. defending.speed-attacking.speed = relative chance of dodging.
40 public var _intellect:int = 1; // Smartness. Opens dialog trees and gives hints.
41 public var _lust:int = 1; // Slowly increases over time, eliminated by masturbation or smecks. Some battles are nonsexual and will not affect lust, others will slightly increase it based on ((number of balls x ball hormone output)+(number of vaginas * vagina hormone output)* sensitivity).
42 public var _sensitivity:Number = 0; // 0-1, 0 being not sensitive
43 public var _HP:int = 100; //100*(level*0.02)
44 public var _XP:int = 0; // 50*(level*0.5)
45 public var _mana:int = 0; // Magic shit, increases over time, especially near relaxing places.
46 public var _gold:int = 0; // Currency
48 // Collections
49 // What magic/techniques can I use?
50 public var _abilities:Object = new Object();
51 // How many, and what type of assholes do I possess?
52 public var _assholes:Vector.<Asshole> = new Vector.<Asshole>();
53 // Needed to attack. Tentacles are ok.
54 public var _arms:Vector.<Arm> = new Vector.<Arm>();
55 // Testes (Cum and pregnancy options)
56 public var _balls:Vector.<Testicle> = new Vector.<Testicle>();
57 // Boobs (fuckable)
58 public var _breasts:Vector.<Breast> = new Vector.<Breast>();
59 // Penises (Pleasure options, testes required for preggo/cum stuff)
60 public var _dicks:Vector.<Penis> = new Vector.<Penis>();
61 // What kinds of effects am I suffering/benefiting from?
62 public var enchantments:Object = new Object();
63 // How many/what kinds of eyes do I have?
64 public var _eyes:Vector.<Eye> = new Vector.<Eye>();
65 // What stuff am I carrying?
66 public var inventory:Vector.<Item> = new Vector.<Item>();
67 // Legs or locomotive tentacles or some other propulsion. (NONE = CAN'T MOVE OR DODGE)
68 public var _legs:Vector.<Leg> = new Vector.<Leg>();
69 // Places to put babies if the "father" has a penis and doesn't know the FALCON PUNCH. Anal pregnancy is okay but only with dicks with that flag.
70 public var _vaginas:Vector.<Vagina> = new Vector.<Vagina>();
71 // For flight.
72 public var _wings:Vector.<Wing> = new Vector.<Wing>();
73 // Explored locations
74 public var explored:Vector.<String> = new Vector.<String>();
76 public var clothing:Vector.<Clothing> = new Vector.<Clothing>();
78 /**
79 * Do stats scale with the PC (false) or stay the same (true)?
80 * Mostly useful for bosses.
82 public var staticStats:Boolean = false;
84 public var main:AdventureController = null;
86 protected var abilityUseProbability:Number = 1;
87 protected var turnsToLose:int = 0;
89 public function Creature()
91 trace("Creature.init()");
92 _gold = MathUtils.rand(0, 50);
93 _mana = maxMana;
96 public function addBreast():Breast
98 trace("USING CREATURE.ADDBREAST INSTEAD OF OVERRIDING");
99 return null;
103 * IT'S A TRAP
104 * @return What the gender LOOKS like, given what you can see with clothing.
106 public function getApparentGender():Gender
108 var canSeeDick:Boolean = false;
109 var canSeeBalls:Boolean = false;
110 var canSeeBoobs:Boolean = false;
111 var canSeeVag:Boolean = false;
113 for each (var d:Penis in dicks)
115 if (d == null)
116 continue;
117 if (!d.isConcealedBy(this, clothing))
119 trace(d.getDescr(1, this), "gave", getTypeName(), "away");
120 canSeeDick = true;
121 break;
125 for each (var t:Testicle in balls)
127 if (t == null)
128 continue;
129 if (!t.isConcealedBy(this, clothing))
131 trace(t.getDescr(1, this), "gave", getTypeName(), "away");
132 canSeeBalls = true;
133 break;
137 for each (var b:Breast in breasts)
139 if (b == null)
140 continue;
141 if (!b.isConcealedBy(this, clothing))
143 trace(b.getDescr(1, this), "gave", getTypeName(), "away");
144 canSeeBoobs = true;
145 break;
149 for each (var v:Vagina in vaginas)
151 if (v == null)
152 continue;
153 if (!v.isConcealedBy(this, clothing))
155 trace(v.getDescr(1, this), "gave", getTypeName(), "away");
156 canSeeVag = true;
157 break;
160 var masc:Boolean = canSeeDick || canSeeBalls;
161 var fem:Boolean = canSeeBoobs || canSeeVag;
162 if (masc && fem)
163 return Gender.HERM;
164 if (masc && !fem)
165 return Gender.MALE;
166 if (!masc && fem)
167 return Gender.FEMALE;
168 return Gender.MALE;
171 public function breastDelta(delta:Number, mult:Boolean):void
173 for (var i:int = 0; i < _breasts.length; i++)
174 if (!mult)
175 _breasts[i].size += (delta);
176 else
177 _breasts[i].milkMult
180 public function dickDelta(delta:Number, mult:Boolean):void
182 for (var i:int = 0; i < _dicks.length; i++)
183 if (mult)
184 _dicks[i].sizeMult += (delta);
185 else
186 _dicks[i].size += (delta);
189 public function testicleDelta(delta:Number, mult:Boolean):void
191 for (var i:int = 0; i < _balls.length; i++)
192 if (mult)
193 _balls[i].loadMult += (delta);
194 else
195 _balls[i].normalLoad += (delta);
198 public function addEnchantment(ench:Enchantment):String
200 var story:String = ench.onInit(this);
201 if (!ench.cancelAddition)
202 this.enchantments[ench.getID()] = ench;
203 return story;
206 public function setupBody():void
208 initialGenderSetup();
209 CONFIG::debug
211 if (this._arms.length == 0)
212 trace("[WARNING] ", this.getTypeName(), " has no arms!");
213 if (this._assholes.length == 0)
214 trace("[WARNING] ", this.getTypeName(), " has no anuses!");
215 if (this._gender.hasDick && this._balls.length == 0)
216 trace("[WARNING] ", this.getTypeName(), " has no balls!");
217 if (this._breasts.length == 0)
218 trace("[WARNING] ", this.getTypeName(), " has no breasts!");
219 if (this._gender.hasDick && this._dicks.length == 0)
220 trace("[WARNING] ", this.getTypeName(), " has no dick!");
221 if (this._eyes.length == 0)
222 trace("[WARNING] ", this.getTypeName(), " has no eyes!");
223 if (this._legs.length == 0)
224 trace("[WARNING] ", this.getTypeName(), " has no legs!");
225 if (this._gender.hasVag && this._vaginas.length == 0)
226 trace("[WARNING] ", this.getTypeName(), " has no vag!");
230 public function initialGenderSetup():void
232 mGenderInitialized = true;
235 public function yourMove(cs:CombatScreen, ply:Creature):void
237 if ((turnsToLose > 0) || notifyEnchantments(new CombatTurnEvent(cs, ply)))
239 InfoScreen.push("<p>The " + getTypeName() + " cannot attack!</p>");
240 return;
242 if (turnsToLose > 0)
244 turnsToLose--;
246 if (MathUtils.lengthOf(abilities) > 0 && MathUtils.rand(0, abilityUseProbability) == 0)
248 var ab:Ability = Ability(MathUtils.getRandomObjectEntry(abilities));
249 if (this.mana < ab.manaCost)
251 InfoScreen.push("<p>The " + getTypeName() + " tried to use " + ab.name + " but is too exhausted!</p>");
252 return;
254 if (ab.activate(this, ply))
256 this.mana -= ab.manaCost
257 return;
260 cs.tryAttack(this, ply);
261 return;
264 public function addDick(type:String = "default"):Penis
266 return null;
269 public function addLust(amt:Number = 1):void
271 var adding2Lust:int = (amt * getLustMult());
272 trace("Adding to lust ", adding2Lust);
273 lust += Math.ceil(adding2Lust);
276 private function getLustMult():Number
278 var numballs:Number = balls.length;
279 var loadMultSum:Number = 0;
280 for (var i:int = 0; i < balls.length; i++)
282 loadMultSum += (balls[i] as Testicle).loadMult * 0.5;
284 return loadMultSum;
287 public function takeFromInventory(item:Item):void
289 for (var i:int = 0; i < inventory.length; i++)
291 if ((inventory[i] as Item).id == item.id)
293 (inventory[i] as Item).amount -= item.amount;
294 if ((inventory[i] as Item).amount <= 0)
295 inventory.splice(i, 1);
296 return;
301 public function addToInventory(item:Item):void
303 for (var i:int = 0; i < inventory.length; i++)
305 if ((inventory[i] as Item).id == item.id)
307 (inventory[i] as Item).amount += item.amount;
308 return;
311 if (inventory.length < 11)
313 inventory.push(item);
315 else
317 if (main != null)
318 main.showInventory(item);
322 public function combatDescr(subj:Creature):String
324 if (getInterested(subj))
326 this.lust = 100;
328 var o:String = "<p>" + Utils.A(getTypeName(), true) + " " + getTypeName() + " leaps from the bushes and attacks!</p><p>Your attacker is ";
329 o += getDescription();
331 return o;
334 public function onEncounter(ply:Creature):Boolean
336 return false;
339 public function onWin(ply:Creature):Boolean
341 return false;
345 * Override this and return true to override the default "YOU WHIN TEH PRIZE!!!!" screen
346 * @param ply
347 * @return
349 public function onLose(ply:Creature):Boolean
351 return false;
354 protected function genName():void
356 var firstNames:Array = ["Andrew", "Alex", "Boris", "Charles", "Alexei", "Drew", "Scruffy", "Gonnadi", "Adolf", "Albert", "Bruno", "Frederick", "Ray"];
358 var lastNames:Array = ["Lenin", "Hitler", "Jenkins", "Balboa", "Nelson", "O'Reilly", "McDonald", "Charles", "Rubin", "Schwarzeneggar"];
359 ownName = MathUtils.getRandomArrayEntry(firstNames) + " " + MathUtils.getRandomArrayEntry(lastNames);
360 //trace(ownName);
363 public function recalcGender():void
365 if (balls.length > 0)
367 if (vaginas.length > 0)
369 gender = Gender.HERM;
371 else
373 gender = Gender.MALE;
376 else
378 if (vaginas.length > 0)
380 gender = Gender.FEMALE;
382 else
384 gender = Gender.ASEXUAL;
390 * What am I?
391 * @return String Whatever it's called
393 public function getTypeName():String
395 throw new Error("SOME DUMBASS DIDN'T GIVE THIS CREATURE A NAME");
396 return "NOT FUCKING NAMED YET";
400 * Do I have the option to run?
401 * @return Button visibility
403 public function canRun():Boolean
405 return true;
408 public function areAnyConcealed(parts:Vector.<IBodyPart>):Boolean
410 var yes:Boolean = false;
411 for each (var p:IBodyPart in parts)
413 if (p != null && p.isConcealedBy(this, clothing))
414 return true;
416 return false;
419 public function isHeadConcealed():Boolean
421 var wat:Function = function(c_:Object, index:int, vector:Vector.<Clothing>):Boolean
423 var c:Clothing = Clothing(c_);
424 if (c != null)
425 return (c.type.obscures.indexOf("head") > -1);
426 else
427 return false;
429 return clothing.some(wat);
432 public function isWearing(ct:ClothingType):Boolean
434 var wat:Function = function(c_:Object, index:int, vector:Vector.<Clothing>):Boolean
436 var c:Clothing = Clothing(c_);
437 if (c != null)
438 return (c.type == ct);
439 else
440 return false;
442 return clothing.some(wat);
445 public function areEyesConcealed():Boolean
447 return areAnyConcealed(Vector.<IBodyPart>(eyes));
450 public function getDescription():String
452 var descr:String = "";
453 // a gay human male of average height and build. He also possesses a long, flowing mane of golden hair,
454 // which contrasts nicely with your blue eyes and light skin.
456 // In the equipment department, you're not too odd. You have two human testicles swinging between your legs, paired with
457 // a single, 5.5" human schlong. Your breasts are flat, but well-sculpted human pecs, and you have a standard-issue male
458 // ass with a standard-issue virgin male asshole between its buns. You've got two human arms, two human legs.
460 // In other words, you're an average human, which probably won't last long down here.
463 // NOW WITH ENEMY TRAPS
464 var aGender:Gender = getApparentGender();
465 descr = Utils.A(sexualPreference.label) + " " + aGender.label + " " + getTypeName() + ", who " + build.getDescription();
467 if (!isHeadConcealed())
469 if (hair == Hair.BALD)
471 descr += ", %POS% glistening scalp";
472 if (!areEyesConcealed())
473 descr += " distracting from %POS%";
475 else
477 descr += ". %CSUB% has " + hair;
478 if (!areEyesConcealed())
479 descr += ", which constrasts nicely with %POS%";
482 else
484 descr += ", and has";
486 if (!areEyesConcealed())
488 if (eyes.length == 0)
490 if (isHeadConcealed())
491 descr += " a";
492 descr += " complete lack of eyes";
494 else
495 descr += getEyesDescr();
496 descr += " and "
499 descr += skin.getDescr(0, this);
500 descr += ".</p>";
502 descr += "<p>In the equipment department, ";
503 var wearingPants:Boolean = isWearing(ClothingType.PANTS);
504 var haveBalls:Boolean = (balls.length > 0 && !wearingPants);
505 var haveDicks:Boolean = (dicks.length > 0 && !wearingPants);
506 var haveVags:Boolean = (vaginas.length > 0 && !wearingPants);
507 if (haveBalls && haveDicks)
508 descr += "%SUB% has " + getTesticleDescr() + " swinging between %POS% legs, paired with " + getDickDescr() + ".";
509 if (!haveBalls && haveDicks)
510 descr += "no testicles rub between %POS% thighs when %SUB% walks, but %SUB% does have " + getDickDescr() + ".";
511 if (haveBalls && !haveDicks)
512 descr += "%SUB% doesn't have a dick, but %SUB% does have " + getTesticleDescr() + ". %SUB% seems to get more horny as time passes.";
514 if (haveVags)
515 descr += " %CPOS% body possesses " + getVagDescr() + ".";
517 if (!haveBalls && !haveDicks && !haveVags )
519 descr += " You can't see any dangly parts, nor anything else between %POS% legs.";
520 if (breasts.length > 0)
521 descr += " However, ";
524 if (breasts.length > 0)
526 descr += " %CSUB% has " + getBreastDescr();
527 if (assholes.length > 0 && !areAnyConcealed(Vector.<IBodyPart>(assholes)))
529 descr += ", and also has " + getAssDescr() + ".";
531 else
533 descr += ".";
536 else
538 descr += " %CSUB% doesn't have any breasts";
539 if (assholes.length > 0 && !areAnyConcealed(Vector.<IBodyPart>(assholes)))
541 descr += ", but does have " + getAssDescr() + ".";
544 else
546 descr += ".";
550 if (arms.length > 0)
551 descr += " %CSUB% has " + getArmsDescr() + ", ";
552 else
553 descr += " %CSUB% doesn't have any arms, ";
555 if (legs.length > 0)
557 if (arms.length == 0)
558 descr += "but %SUB% DOES have ";
559 else
560 descr += "and ";
561 descr += getLegsDescr() + ".";
563 else
564 descr += "and no legs.";
566 if (wings.length > 0)
568 descr += " %CSUB% also has " + getWingsDescr() + ".";
571 descr += "</p>";
573 descr += "<p>%CSUB% is wearing " + ((clothing.length > 0) ? "a " + getClothingDescr() : "nothing") + ".</p>";
574 if (aGender.label != gender.label)
575 descr += "<p><small>DEBUG: %CSUB% is actually a " + gender.label + " with " + getDickDescr() + "/" + getTesticleDescr() + "/" + getVagDescr() + ". TEE HEE.</small></p>";
577 return aGender.doReplace(descr);
580 public function hasEnchantment(name:String):Boolean
582 return Utils.objHas(enchantments, name);
585 public function levelUp(firstOne:Boolean = false):void
587 _level++;
588 if (!firstOne)
589 InfoScreen.push("<h2>Levelled up!</h2><p>You are now at level " + level + "!</p>");
592 public function onCombatInit(ply:Player):void
594 HP = this.maxHP;
597 public function get maxMana():int
599 return 100 + ((level - 1) * 10);
602 public function get maxHP():int
604 return 100 + ((level - 1) * 10);
607 public function get maxXP():int
609 return Math.max(1, 50 * (_level * 0.5));
612 public function getExplored(loc:String):Boolean
614 for (var i:int = 0; i < explored.length; i++)
616 if (explored[i] == loc)
617 return true;
619 return false;
622 public function setExplored(loc:String):void
624 if (getExplored(loc))
625 return;
626 explored.push(loc);
629 public function getEffectivenessMultiplier(defender:Creature):Number
631 var a:Number = strength;
632 var e:Number = defender.strength;
633 return (a * (100 - e)) / 10000;
637 * Calculation from http://www.gamedev.net/topic/183822-rpg-combat-formula-question/
638 * @param attacker
640 public function speedCheckAgainst(attacker:Creature):Boolean
642 // C = A * (100% - E)
643 // WHERE
644 // C = Chance to hit
645 // A = Attacker's accuracy (speed, in our case)
646 // E = Defender's evasion rate (speed, again)
647 var a:Number = attacker.speed;
648 var e:Number = speed;
649 return Math.random() <= (a * (100 - e)) / 10000;
653 * Calculation from http://www.gamedev.net/topic/183822-rpg-combat-formula-question/
654 * @param attacker
656 public function strengthCheckAgainst(attacker:Creature):Boolean
658 var a:Number = attacker.strength;
659 var e:Number = strength;
660 // C = A * (100% - E)
661 // WHERE
662 // C = Chance to hit
663 // A = Attacker's accuracy (strength, in our case)
664 // E = Defender's evasion rate (strength, again)
665 return Math.random() <= (a * (100 - e)) / 10000;
669 * Figure out how much shit we're going to wreck.
670 * @param attacker
671 * @param weapon or null
672 * @return
674 public function damageAgainst(attacker:Creature, weapon:IWeapon):Number
676 // from D&D?
677 // TODO: Probably need to factor in speed or something at some point. I ain't a math guy.
678 var a:Number = attacker.strength;
679 var e:Number = strength;
680 var weaponDamage:Number = 0;
681 if (weapon != null)
682 weaponDamage = weapon.calcDamage(this, attacker);
683 var dmg:Number = (MathUtils.rand(0, 1, false) + level + (strength / 50) + weaponDamage) - (MathUtils.rand(0, 1, false) + attacker.level + (attacker.strength / 50));
684 dmg *= 10;
685 return Math.ceil((dmg > 0) ? dmg : 1); // Keep above 1 (no negatives, no 0-damage attacks.)
688 public function get strength():int
690 return _strength;
693 public function set strength(str:int):void
695 _strength = str;
696 doStatsUpdate();
699 public function get speed():int
701 return _speed;
704 public function set speed(spd:int):void
706 _speed = spd;
707 doStatsUpdate();
710 public function get lust():int
712 return _lust;
715 public function set lust(lst:int):void
717 _lust = lst;
718 if (_lust > 100)
719 _lust = 100;
720 doStatsUpdate();
723 public function get gold():int
725 return _gold;
728 public function set gold(value:int):void
730 if (value < 0)
731 value = 0;
732 _gold = value;
733 doStatsUpdate();
736 public function get intellect():int
738 return _intellect;
741 public function set intellect(i:int):void
743 _intellect = i;
744 doStatsUpdate();
747 public function get mana():int
749 return _mana;
752 public function set mana(i:int):void
754 _mana = i;
755 doStatsUpdate();
758 public function get sensitivity():int
760 return _sensitivity;
763 public function set sensitivity(i:int):void
765 _sensitivity = i;
766 doStatsUpdate();
769 public function get assholes():Vector.<Asshole>
771 return this._assholes;
774 public function set assholes(balls:Vector.<Asshole>):void
776 this._assholes = balls;
777 customized = true;
780 public function hasItem(id:int):Boolean
782 for each (var item:Item in this.inventory)
784 if (item.id == id)
785 return true;
787 return false;
790 public function get breasts():Vector.<Breast>
792 return this._breasts;
795 public function set breasts(balls:Vector.<Breast>):void
797 this._breasts = balls;
798 customized = true;
801 public function get eyes():Vector.<Eye>
803 return this._eyes;
806 public function set eyes(balls:Vector.<Eye>):void
808 this._eyes = balls;
809 customized = true;
812 public function get vaginas():Vector.<Vagina>
814 return this._vaginas;
817 public function set vaginas(balls:Vector.<Vagina>):void
819 this._vaginas = balls;
820 customized = true;
823 public function get arms():Vector.<Arm>
825 return _arms;
828 public function set arms(arr:Vector.<Arm>):void
830 _arms = arr;
831 customized = true;
834 public function get legs():Vector.<Leg>
836 return _legs;
839 public function set legs(arr:Vector.<Leg>):void
841 _legs = arr;
842 customized = true;
845 public function get wings():Vector.<Wing>
847 return _wings;
850 public function set wings(arr:Vector.<Wing>):void
852 _wings = arr;
853 customized = true;
856 public function get balls():Vector.<Testicle>
858 return _balls;
861 public function set balls(balls:Vector.<Testicle>):void
863 _balls = balls;
864 customized = true;
867 public function get dicks():Vector.<Penis>
869 return _dicks;
872 public function set dicks(aaa:Vector.<Penis>):void
874 _dicks = aaa;
875 customized = true;
878 public function get abilities():Object
880 return _abilities;
883 public function set abilities(arr:Object):void
885 _abilities = arr;
888 public function get gender():Gender
890 return _gender;
893 public function set gender(value:Gender):void
895 _gender = value;
896 customized = true;
899 public function get HP():int
901 return _HP;
904 public function set HP(value:int):void
906 _HP = value;
907 doStatsUpdate();
910 public function get XP():int
912 return _XP;
915 public function set XP(value:int):void
917 //trace("XP", value);
918 _XP = value;
919 if (_XP >= maxXP)
921 _XP = 0;
922 levelUp();
924 doStatsUpdate();
927 public function setMain(main:AdventureController):void
929 this.main = main;
932 private function doStatsUpdate():void
934 if (main != null)
936 main.refreshStats();
938 else
940 // AI
941 if (_eyes.length == 0)
942 _speed = 0.1; // 1/10 chance of hitting when blind
946 public function get level():int
948 return _level;
951 private function getBodyPartDesc(collection:Vector.<IBodyPart>, singular:String):String
954 if (collection.length == 0)
956 return "no " + Utils.pluralize(2, singular);
958 var out:String = "";
959 var varying:Boolean = false;
960 var types:Object = new Object();
961 var lname:String = "";
962 var numtypes:Number = 0;
963 for each (var i:*in collection)
965 var t:IBodyPart = i as IBodyPart;
966 if (t == null)
967 continue;
968 //trace(t);
969 lname = t.name;
970 if (!(lname in types))
972 types[lname] = 0;
973 numtypes++;
975 types[lname]++;
977 if (numtypes == 1)
979 for each (t in collection)
981 if (t.name == lname)
982 return t.getDescr(types[lname], this);
985 else
987 var n:Number = 0;
988 for (var ot:*in types)
990 var gotdescr:Boolean = false;
991 for each (t in collection)
993 if (t.name == ot)
995 if (!gotdescr)
997 out += ", " + t.getDescr(types[ot] as Number, this);
998 gotdescr = true;
1000 n += types[ot];
1004 return collection.length + " " + singular + "s of varying types (" + out.substr(2) + ")";
1006 return "";
1009 public function notifyEnchantments(e:*):Boolean
1011 var collection:Array = [];
1012 for (var eID:String in enchantments)
1014 var ench:Enchantment = enchantments[eID];
1015 if (e is CombatStartEvent)
1017 ench.onCombatInit(e.other);
1019 if (e is CombatEndEvent)
1021 ench.onCombatComplete(e.won, e.other);
1023 if (e is CombatTurnEvent)
1025 return ench.onMyCombatTurn(e.screen, e.other);
1028 return false;
1031 public function inventoryUpdate(item:Item, received:Boolean):Boolean
1033 var actionToTake:int = -1;
1034 for (var eID:String in enchantments)
1036 var act:int = enchantments[eID].onInventoryReceived(item);
1037 if (act != Enchantment.INTERCEPT_ACTION_NONE)
1039 actionToTake = act;
1040 break;
1043 switch (actionToTake)
1045 case Enchantment.INTERCEPT_ACTION_TOSS:
1046 // Do nothing, we're already tossing.
1047 break;
1048 case Enchantment.INTERCEPT_ACTION_USE:
1049 item.Use(this);
1050 break;
1051 default:
1052 break;
1054 return actionToTake == Enchantment.INTERCEPT_ACTION_NONE;
1057 public function getTesticleDescr():String
1059 return getBodyPartDesc(Vector.<IBodyPart>(balls), "ball");
1062 public function getBulgesInPants():String
1064 var numBulge:int = 0;
1065 var peeks:Vector.<Penis> = new Vector.<Penis>();
1066 for each (var p:Penis in dicks)
1068 if (p == null)
1069 continue;
1070 if (!p.isConcealedBy(this, clothing))
1072 for each (var c:Clothing in clothing)
1074 if (c == null)
1075 continue;
1076 var bsize:Number = p.getBulgeSize(this, c);
1077 trace(p.getDescr(1, this), "bsize=" + bsize.toString());
1078 if (bsize > 6)
1080 if (bsize < 8)
1082 numBulge++;
1084 else
1086 peeks.push(p)
1092 if (numBulge == 0 && peeks.length == 0)
1093 return "";
1094 var fo:String = " (which has ";
1095 if (numBulge > 0)
1097 fo += numBulge + " " + Utils.pluralize(numBulge, "bulge", "bulges");
1099 if (numBulge > 0 && peeks.length > 0)
1101 fo += " and ";
1103 if (peeks.length > 0)
1105 fo += getBodyPartDesc(Vector.<IBodyPart>(peeks), "dick") + " peeking over %POS% waistband";
1107 return fo + ")";
1110 public function getDickDescr():String
1112 return getBodyPartDesc(Vector.<IBodyPart>(dicks), "dick");
1115 public function getVagDescr():String
1117 return getBodyPartDesc(Vector.<IBodyPart>(vaginas), "vag");
1120 public function getBreastDescr():String
1122 return getBodyPartDesc(Vector.<IBodyPart>(breasts), "boob");
1125 public function getAssDescr():String
1127 return getBodyPartDesc(Vector.<IBodyPart>(assholes), "asshole");
1130 public function getArmsDescr():String
1132 return getBodyPartDesc(Vector.<IBodyPart>(arms), "arm");
1135 public function getEyesDescr():String
1137 return getBodyPartDesc(Vector.<IBodyPart>(eyes), "eye");
1140 public function getLegsDescr():String
1142 return getBodyPartDesc(Vector.<IBodyPart>(legs), "leg");
1145 public function getWingsDescr():String
1147 return getBodyPartDesc(Vector.<IBodyPart>(wings), "wing");
1150 public function getClothingDescr():String
1152 var desc:String = "";
1154 for (var i:int = 0; i < clothing.length; i++)
1156 var item:Clothing = clothing[i];
1158 desc += item.getDescr(this);
1160 switch (item.type)
1162 case ClothingType.HEADGEAR:
1163 desc += " as a hat";
1164 break;
1165 case ClothingType.TOP:
1166 desc += " as a shirt";
1167 break;
1168 case ClothingType.FOOTWEAR:
1169 desc += " as shoes";
1170 break;
1171 case ClothingType.PANTS:
1172 desc += " as trousers" + getBulgesInPants();
1173 break;
1176 if (i < (clothing.length - 3))
1178 desc += ", ";
1180 else if (i == (clothing.length - 2))
1182 desc += " and ";
1186 return desc;
1190 * Wants your body
1192 * I = Interested
1193 * H = Hostile
1194 * +---------------+---+---+
1195 * | Type | I | H |
1196 * +---------------+---+---+
1197 * | Rape | T | T |
1198 * | Fight | F | T |
1199 * | Horny | T | F |
1200 * | - | F | F |
1201 * +---------------+---+---+
1203 public function getInterested(subj:Creature):Boolean
1205 return sexualPreference.isOppositeGender(gender, subj.getApparentGender()); // trollface.jpg
1209 * By default, only allow rape if health == 0 or paralyzed.
1210 * @param rapist WHO BE RAPIN ME
1213 public function tryRape(rapist:Creature):Boolean
1215 return (HP == 0 || Paralyze.isParalyzed(this));
1219 public function getHostile(subj:Creature):Boolean
1221 return false;
1224 public function performConversion(oldMe:Creature):void
1229 public function changeFrom(f:Creature):void
1231 this.performConversion(f);
1234 public function loseTurns(numturns:int):void
1236 turnsToLose += numturns;
1239 public function getRapable():Boolean
1241 return canRun() && HP < (maxHP / 3);
1245 * Alter the rape menu to fit your needs.
1246 * @param ply
1247 * @param menu
1249 public function onRape(ply:Creature, rape:Rape):void