Fix Hunger implementation
[18plus-7leafadventure.git] / src / org / sevenchan / dongs / Creature.as
blobe6f64276dcdce38d46009957adb2ed04162a826c
1 package org.sevenchan.dongs
3 import flash.media.ID3Info;
4 import org.sevenchan.AdventureController;
5 import flash.net.*;
6 import org.sevenchan.dongs.bodyparts.*;
7 import org.sevenchan.dongs.bodyparts.asshole.Abdomen;
8 import org.sevenchan.dongs.bodyparts.eye.GhostEye;
9 import org.sevenchan.dongs.creature.*;
10 import org.sevenchan.dongs.enchantment.*;
11 import org.sevenchan.dongs.enchantment.events.*;
12 import org.sevenchan.dongs.screens.*;
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. 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 /**
77 * Do stats scale with the PC (false) or stay the same (true)?
78 * Mostly useful for bosses.
80 public var staticStats:Boolean = false;
82 private var main:AdventureController = null;
85 protected var abilityUseProbability:Number = 1;
86 protected var turnsToLose:int = 0;
88 public function Creature()
90 trace("Creature.init()");
91 _gold = MathUtils.rand(0, 50);
92 _mana = maxMana;
95 public function addBreast():Breast
97 trace("USING CREATURE.ADDBREAST INSTEAD OF OVERRIDING");
98 return null;
101 public function addEnchantment(ench:Enchantment):String
103 var story:String = ench.onInit(this);
104 if (!ench.cancelAddition)
105 this.enchantments[ench.getID()] = ench;
106 return story;
109 public function initialGenderSetup():void
111 mGenderInitialized = true;
114 public function yourMove(cs:CombatScreen, ply:Creature):void
116 if ((turnsToLose > 0) || notifyEnchantments(new CombatTurnEvent(cs,ply)))
118 InfoScreen.push("<p>The " + getTypeName() + " cannot attack!</p>");
119 return;
121 if (turnsToLose > 0)
123 turnsToLose--;
125 if (MathUtils.lengthOf(abilities) > 0 && MathUtils.rand(0, abilityUseProbability) == 0)
127 var ab:Ability = Ability(MathUtils.getRandomObjectEntry(abilities));
128 if (this.mana < ab.manaCost)
130 InfoScreen.push("<p>The " + getTypeName() + " tried to use " + ab.name + " but is too exhausted!</p>");
131 return;
133 if (ab.activate(this, ply))
135 this.mana -= ab.manaCost
136 return;
139 cs.tryAttack(this, ply);
140 return;
143 public function addDick(type:String = "default"):Penis
145 return null;
148 public function addLust(amt:Number = 1):void
150 var adding2Lust:int = (amt * getLustMult());
151 trace("Adding to lust ", adding2Lust);
152 lust += Math.ceil(adding2Lust);
155 private function getLustMult():Number
157 var numballs:Number = balls.length;
158 var loadMultSum:Number = 0;
159 for (var i:int = 0; i < balls.length; i++)
161 loadMultSum += (balls[i] as Testicle).loadMult * 0.5;
163 return loadMultSum;
166 public function takeFromInventory(item:Item):void
168 for (var i:int = 0; i < inventory.length; i++)
170 if ((inventory[i] as Item).id == item.id)
172 (inventory[i] as Item).amount -= item.amount;
173 if ((inventory[i] as Item).amount <= 0)
174 inventory.splice(i, 1);
175 return;
180 public function addToInventory(item:Item):void
182 for (var i:int = 0; i < inventory.length; i++)
184 if ((inventory[i] as Item).id == item.id)
186 (inventory[i] as Item).amount += item.amount;
187 return;
190 if (inventory.length < 11)
192 inventory.push(item);
194 else
196 if (main != null)
197 main.showInventory(item);
201 public function combatDescr(subj:Creature):String
203 if (getInterested(subj))
205 this.lust = 100;
207 var o:String = "<p>" + Utils.A(getTypeName(), true) + " " + getTypeName() + " leaps from the bushes and attacks!</p><p>Your attacker is ";
208 o += getDescription();
210 return o;
213 public function onEncounter(ply:Creature):Boolean
215 return false;
218 public function onWin(ply:Creature):Boolean
220 return false;
223 public function onLose(ply:Creature):Boolean
225 return false;
228 protected function genName():void
230 var firstNames:Array = ["Andrew", "Alex", "Boris", "Charles", "Alexei", "Drew", "Scruffy", "Gonnadi", "Adolf", "Albert", "Bruno", "Frederick", "Ray"];
232 var lastNames:Array = ["Lenin", "Hitler", "Jenkins", "Balboa", "Nelson", "O'Reilly", "McDonald", "Charles", "Rubin", "Schwarzeneggar"];
233 ownName = MathUtils.getRandomArrayEntry(firstNames) + " " + MathUtils.getRandomArrayEntry(lastNames);
234 //trace(ownName);
237 public function recalcGender():void
239 if (balls.length > 0)
241 if (vaginas.length > 0)
243 gender = Gender.HERM;
245 else
247 gender = Gender.MALE;
250 else
252 if (vaginas.length > 0)
254 gender = Gender.FEMALE;
256 else
258 gender = Gender.ASEXUAL;
264 * What am I?
265 * @return String Whatever it's called
267 public function getTypeName():String
269 throw new Error("SOME DUMBASS DIDN'T GIVE THIS CREATURE A NAME");
270 return "NOT FUCKING NAMED YET";
274 * Do I have the option to run?
275 * @return Button visibility
277 public function canRun():Boolean
279 return true;
282 public function getDescription():String
284 var descr:String = "";
285 // a gay human male of average height and build. He also possesses a long, flowing mane of golden hair,
286 // which contrasts nicely with your blue eyes and light skin.
288 // In the equipment department, you're not too odd. You have two human testicles swinging between your legs, paired with
289 // a single, 5.5" human schlong. Your breasts are flat, but well-sculpted human pecs, and you have a standard-issue male
290 // ass with a standard-issue virgin male asshole between its buns. You've got two human arms, two human legs.
292 // In other words, you're an average human, which probably won't last long down here.
294 descr = Utils.A(sexualPreference.label) + " " + sexualPreference.label + " " + gender.label + " " + getTypeName() + ", who " + build.getDescription() + " %CSUB% also possesses " + hair.getDescription();
296 if (hair == Hair.BALD)
297 descr += ", %POS% glistening scalp distracting from %POS% ";
298 else
299 descr += ", which constrasts nicely with %POS% ";
300 if (eyes.length == 0)
301 descr += " complete lack of eyes (<b>and resulting blindness</b>)";
302 else
303 descr += getEyesDescr();
305 descr += " and " + skin.getDescr(0, this);
306 descr += ".</p>";
308 descr += "<p>In the equipment department, ";
309 var haveBalls:Boolean = (balls.length > 0);
310 var haveDicks:Boolean = (dicks.length > 0);
311 var haveVags:Boolean = (vaginas.length > 0);
312 if (haveBalls && haveDicks)
313 descr += "%SUB% has " + getTesticleDescr() + " swinging between %POS% legs, paired with " + getDickDescr() + ".";
314 if (!haveBalls && haveDicks)
315 descr += "no testicles rub between %POS% thighs when %SUB% walks, but %SUB% does have " + getDickDescr() + ".";
316 if (haveBalls && !haveDicks)
317 descr += "%SUB% doesn't have a dick, but %SUB% does have " + getTesticleDescr() + ". %SUB% seems to get more horny as time passes.";
319 if (haveVags)
320 descr += " %CPOS% body possesses " + getVagDescr() + ".";
322 if (!haveBalls && !haveDicks && !haveVags)
323 descr += " %CSUB% doesn't have any sexual organs. At least you won't get raped.";
325 if (breasts.length > 0) {
326 descr += " %CSUB% has " + getBreastDescr();
327 if(assholes.length>0) {
328 descr += ", and also has "+getAssDescr() + ".";
329 } else {
330 descr += ", but does not have any rectal orifaces to speak of.";
332 }else{
333 descr += " %CSUB% doesn't have any breasts";
334 if(assholes.length>0) {
335 descr += ", but does have "+getAssDescr() + ".";;
336 } else {
337 descr += ", nor do you see any rectal orifaces.";
341 if (arms.length > 0)
342 descr += " %CSUB% has " + getArmsDescr() + ", ";
343 else
344 descr += " %CSUB% doesn't have any arms (<b>and therefore can't attack</b>), ";
346 if (legs.length > 0)
348 if (arms.length == 0)
349 descr += "but %SUB% DOES have ";
350 else
351 descr += "and ";
352 descr += getLegsDescr() + ".";
354 else
355 descr += "and no legs (<b>so %SUB% can't dodge attacks</b>).";
357 if (wings.length > 0)
359 descr += " %CSUB% also has " + getWingsDescr() + ".";
361 descr += "</p>";
363 return gender.doReplace(descr);
366 public function hasEnchantment(name:String):Boolean
368 return Utils.objHas(enchantments, name);
371 public function levelUp(firstOne:Boolean = false):void
373 _level++;
374 if (!firstOne)
375 InfoScreen.push("<h2>Levelled up!</h2><p>You are now at level " + level + "!</p>");
378 public function onCombatInit():void
380 HP = this.maxHP;
383 public function get maxMana():int
385 return 100 + ((level - 1) * 10);
388 public function get maxHP():int
390 return 100 + ((level - 1) * 10);
393 public function get maxXP():int
395 return Math.max(1, 50 * (_level * 0.5));
398 public function getExplored(loc:String):Boolean
400 for (var i:int = 0; i < explored.length; i++)
402 if (explored[i] == loc)
403 return true;
405 return false;
408 public function setExplored(loc:String):void
410 if (getExplored(loc))
411 return;
412 explored.push(loc);
415 public function getEffectivenessMultiplier(defender:Creature):Number {
416 var a:Number = strength;
417 var e:Number = defender.strength;
418 return (a * (100 - e))/10000;
422 * Calculation from http://www.gamedev.net/topic/183822-rpg-combat-formula-question/
423 * @param attacker
425 public function speedCheckAgainst(attacker:Creature):Boolean {
426 // C = A * (100% - E)
427 // WHERE
428 // C = Chance to hit
429 // A = Attacker's accuracy (speed, in our case)
430 // E = Defender's evasion rate (speed, again)
431 var a:Number = attacker.speed;
432 var e:Number = speed;
433 return Math.random() <= (a * (100 - e))/10000;
437 * Calculation from http://www.gamedev.net/topic/183822-rpg-combat-formula-question/
438 * @param attacker
440 public function strengthCheckAgainst(attacker:Creature):Boolean {
441 // C = A * (100% - E)
442 // WHERE
443 // C = Chance to hit
444 // A = Attacker's accuracy (strength, in our case)
445 // E = Defender's evasion rate (strength, again)
446 var a:Number = attacker.strength;
447 var e:Number = strength;
448 return Math.random() <= (a * (100 - e))/10000;
451 public function get strength():int
453 return _strength;
456 public function set strength(str:int):void
458 _strength = str;
459 doStatsUpdate();
462 public function get speed():int
464 return _speed;
467 public function set speed(spd:int):void
469 _speed = spd;
470 doStatsUpdate();
473 public function get lust():int
475 return _lust;
478 public function set lust(lst:int):void
480 _lust = lst;
481 if (_lust > 100)
482 _lust = 100;
483 doStatsUpdate();
486 public function get gold():int
488 return _gold;
491 public function set gold(value:int):void
493 if (value < 0)
494 value = 0;
495 _gold = value;
496 doStatsUpdate();
499 public function get intellect():int
501 return _intellect;
504 public function set intellect(i:int):void
506 _intellect = i;
507 doStatsUpdate();
510 public function get mana():int
512 return _mana;
515 public function set mana(i:int):void
517 _mana = i;
518 doStatsUpdate();
521 public function get sensitivity():int
523 return _sensitivity;
526 public function set sensitivity(i:int):void
528 _sensitivity = i;
529 doStatsUpdate();
532 public function get assholes():Vector.<Asshole>
534 return this._assholes;
537 public function set assholes(balls:Vector.<Asshole>):void
539 this._assholes = balls;
540 customized = true;
543 public function hasItem(id:int):Boolean {
544 for each (var item:Item in this.inventory) {
545 if (item.id == id)
546 return true;
548 return false;
550 public function get breasts():Vector.<Breast>
552 return this._breasts;
555 public function set breasts(balls:Vector.<Breast>):void
557 this._breasts = balls;
558 customized = true;
561 public function get eyes():Vector.<Eye>
563 return this._eyes;
566 public function set eyes(balls:Vector.<Eye>):void
568 this._eyes = balls;
569 customized = true;
572 public function get vaginas():Vector.<Vagina>
574 return this._vaginas;
577 public function set vaginas(balls:Vector.<Vagina>):void
579 this._vaginas = balls;
580 customized = true;
583 public function get arms():Vector.<Arm>
585 return _arms;
588 public function set arms(arr:Vector.<Arm>):void
590 _arms = arr;
591 customized = true;
594 public function get legs():Vector.<Leg>
596 return _legs;
599 public function set legs(arr:Vector.<Leg>):void
601 _legs = arr;
602 customized = true;
605 public function get wings():Vector.<Wing>
607 return _wings;
610 public function set wings(arr:Vector.<Wing>):void
612 _wings = arr;
613 customized = true;
616 public function get balls():Vector.<Testicle>
618 return _balls;
621 public function set balls(balls:Vector.<Testicle>):void
623 _balls = balls;
624 customized = true;
627 public function get dicks():Vector.<Penis>
629 return _dicks;
632 public function set dicks(balls:Vector.<Penis>):void
634 _dicks = balls;
635 customized = true;
638 public function get abilities():Object
640 return _abilities;
643 public function set abilities(arr:Object):void
645 _abilities = arr;
648 public function get gender():Gender
650 return _gender;
653 public function set gender(value:Gender):void
655 _gender = value;
656 customized = true;
659 public function get HP():int
661 return _HP;
664 public function set HP(value:int):void
666 _HP = value;
667 doStatsUpdate();
670 public function get XP():int
672 return _XP;
675 public function set XP(value:int):void
677 //trace("XP", value);
678 _XP = value;
679 if (_XP >= maxXP)
681 _XP = 0;
682 levelUp();
684 doStatsUpdate();
687 public function setMain(main:AdventureController):void
689 this.main = main;
692 private function doStatsUpdate():void
694 if (main != null)
696 main.refreshStats();
700 public function get level():int
702 return _level;
705 private function getBodyPartDesc(collection:Vector.<IBodyPart>, singular:String):String
708 if (collection.length == 0)
710 return "no " + Utils.pluralize(2,singular);
712 var out:String = "";
713 var varying:Boolean = false;
714 var types:Object = new Object();
715 var lname:String = "";
716 var numtypes:Number = 0;
717 for each (var i:*in collection)
719 var t:IBodyPart = i as IBodyPart;
720 if (t == null)
721 continue;
722 //trace(t);
723 lname = t.name;
724 if (!(lname in types))
726 types[lname] = 0;
727 numtypes++;
729 types[lname]++;
731 for (var k:String in types)
733 trace(k + " = " + types[k]);
735 if (numtypes == 1)
737 for each (t in collection)
739 if (t.name == lname)
740 return t.getDescr(types[lname], this);
743 else
745 var n:Number = 0;
746 for (var ot:*in types)
748 var gotdescr:Boolean = false;
749 for each (t in collection)
751 if (t.name == ot)
753 if (!gotdescr)
755 out += ", " + t.getDescr(types[ot] as Number, this);
756 gotdescr = true;
758 n += types[ot];
762 return collection.length + " " + singular + "s of varying types (" + out.substr(2) + ")";
764 return "";
767 public function notifyEnchantments(e:*):Boolean
769 var collection:Array = [];
770 for (var eID:String in enchantments)
772 var ench:Enchantment = enchantments[eID];
773 if (e is CombatStartEvent)
775 ench.onCombatInit(e.other);
777 if (e is CombatEndEvent)
779 ench.onCombatComplete(e.won, e.other);
781 if (e is CombatTurnEvent)
783 return ench.onMyCombatTurn(e.screen,e.other);
786 return false;
790 public function inventoryUpdate(item:Item,received:Boolean):Boolean
792 var actionToTake:int = -1;
793 for (var eID:String in enchantments)
795 var act:int = enchantments[eID].onInventoryReceived(item);
796 if (act != Enchantment.INTERCEPT_ACTION_NONE) {
797 actionToTake = act;
798 break;
801 switch(actionToTake) {
802 case Enchantment.INTERCEPT_ACTION_TOSS:
803 // Do nothing, we're already tossing.
804 break;
805 case Enchantment.INTERCEPT_ACTION_USE:
806 item.Use(this);
807 break;
808 default:
809 break;
811 return actionToTake==Enchantment.INTERCEPT_ACTION_NONE;
814 public function getTesticleDescr():String
816 return getBodyPartDesc(Vector.<IBodyPart>(balls), "ball");
819 public function getDickDescr():String
821 return getBodyPartDesc(Vector.<IBodyPart>(dicks), "dick");
824 public function getVagDescr():String
826 return getBodyPartDesc(Vector.<IBodyPart>(vaginas), "vag");
829 public function getBreastDescr():String
831 return getBodyPartDesc(Vector.<IBodyPart>(breasts), "boob");
834 public function getAssDescr():String
836 return getBodyPartDesc(Vector.<IBodyPart>(assholes), "asshole");
839 public function getArmsDescr():String
841 return getBodyPartDesc(Vector.<IBodyPart>(arms), "arm");
844 public function getEyesDescr():String
846 return getBodyPartDesc(Vector.<IBodyPart>(eyes), "eye");
849 public function getLegsDescr():String
851 return getBodyPartDesc(Vector.<IBodyPart>(legs), "leg");
854 public function getWingsDescr():String
856 return getBodyPartDesc(Vector.<IBodyPart>(wings), "wing");
860 * Wants your body
862 * I = Interested
863 * H = Hostile
864 * +---------------+---+---+
865 * | Type | I | H |
866 * +---------------+---+---+
867 * | Rape | T | T |
868 * | Fight | F | T |
869 * | Horny | T | F |
870 * | - | F | F |
871 * +---------------+---+---+
873 public function getInterested(subj:Creature):Boolean
875 return sexualPreference.isOppositeGender(gender, subj.gender);
878 public function getHostile(subj:Creature):Boolean
880 return false;
883 public function performConversion(oldMe:Creature):void
888 public function changeFrom(f:Creature):void
890 this.performConversion(f);
893 public function loseTurns(numturns:int):void
895 turnsToLose += numturns;
898 public function getRapable():Boolean {
899 return canRun();