The Cathedral of Attnam

Iter Vehemens ad Necem (IVAN)
Login
Username
Password


 Valid CSS  Valid HTML 4.01 Strict

Coding the AI to throw items!!!

The Cathedral of Attnam  >  Programming
Print

View profile
Send message
Find posts Find topics
 
Feb 5, 2011 at 8:03 am #1  !
Warheck's Avatar
Warheck
kobold lord


Joined: Sep 9, 2010
Occupation: Petty Functionary
Location: Eating pea soup in the world map
Interests: Mangoes
Posts: 122
Groups:
Coding the AI to throw items!!!
I have developed a stable algorithm principally for use in LIVAN, but could concievably be used in IVAN, which enables the AI to throw certain items at hostile creatures in the game. It is the result of several hours of sourcediving and general fooling around with the code.

The algorithm itself is straightforward:

- The thrower has to be humanoid, among other things.
- Has to have at least one arm
- Has to be a ranged attacker (this is new)
- First he checks the area for hostiles he can see:
He looks in all eight directions for a suitable throwing direction, free from friendlies and a direction that contains the nearest hostile. The status of the directions are stored in a buffer; they will either be ZERO, SUCCESS or BLOCKED.
- Once he has checked out the whole area, and has a SUCCESS direction, he checks his inventory for a suitable throwing weapon. The throwing weapons have been implemented as AXE and DAGGER in this case.
- If he has something suitable to throw, he will throw that item in the direction of the hostile he picked up on his radar

Now for practical purposes, the thrower has been implemented as a novel dwarf type character, "axethrowerdwarf", resembling a kamakaze dwarf, but without the backpack.
There is also a modification to the "CheckForUsefulItemsOnGround", where the dwarf will pick up suitable objects he can throw, and hoards them in his inventory for later use. That way he can re-stock his ammo.

The axethrower dwarf may seem a little underpowered, however, this algorithm is designed to provide scope for anyone who wants to create the abominable "Grenadier Dwarves" that have been mentioned somewhere...
That would require a simple change to some of the gas-grenade item-properties in the script, and perhaps a change to the Grenadier Dwarf's initial equipment :E

I hope I have catalogued everything that is required, let me know if it doesn't compile. Code additions are in bold-faced type. Here it is:


Code



// To make the AI throw items, add the following lines of code:

// In human.h:


CHARACTER(humanoid, character)
{
public:
...
virtual truth CheckThrowItemOpportunity();
...
}

CHARACTER(axethrowerdwarf, humanoid)
{
public:
virtual void GetAICommand();
virtual void CreateInitialEquipment(int);
protected:
virtual int GetTorsoMainColor() const;
virtual int GetGauntletColor() const;
virtual int GetLegMainColor() const;
virtual v2 GetDrawDisplacement(int) const;
virtual int GetWSkillHits() const { return 10000; }
virtual truth IsElite() const { return false; }
};


// In human.cpp:

void axethrowerdwarf::CreateInitialEquipment(int SpecialFlags)
{
SetRightWielded(meleeweapon::Spawn(AXE, SpecialFlags));
SetLeftWielded(meleeweapon::Spawn(AXE, SpecialFlags));
for(int k = 0; k < 6; k++)
{
GetStack()->AddItem(meleeweapon::Spawn(AXE));
}
GetStack()->AddItem(lantern::Spawn());
GetCWeaponSkill(AXES)->AddHit(GetWSkillHits());
GetCurrentRightSWeaponSkill()->AddHit(GetWSkillHits());
}

void axethrowerdwarf::GetAICommand()
{
if(CheckThrowItemOpportunity())
return;

character::GetAICommand();
}

v2 axethrowerdwarf::GetDrawDisplacement(int j) const
{
static v2 DrawDisplacement[] = { v2(0, 0), v2(0, 1), v2(0, -1), v2(0, -1), v2(0, -1), v2(0, 0), v2(0, 0) };
return DrawDisplacement[j];
}

col16 axethrowerdwarf::GetTorsoMainColor() const
{
return GetMasterGod()->GetColor();
}

col16 axethrowerdwarf::GetGauntletColor() const
{
return GetMasterGod()->GetColor();
}

col16 axethrowerdwarf::GetLegMainColor() const
{
return GetMasterGod()->GetColor();
}

truth humanoid::CheckThrowItemOpportunity()
{
if(!HasAUsableArm())
return false;
else
return character::CheckThrowItemOpportunity();
}


// In char.dat:

character
{
...
IsRangedAttacker = false;
}

axethrowerdwarf
{
DefaultArmStrength = 20;
DefaultLegStrength = 20;
DefaultDexterity = 20;
DefaultAgility = 10;
DefaultEndurance = 12;
DefaultPerception = 18;
DefaultIntelligence = 10;
DefaultWisdom = 5;
DefaultCharisma = 10;
DefaultMana = 10;
HeadBitmapPos = 112, 160;
TorsoBitmapPos = 48, 16;
ArmBitmapPos = 80, 0;
LegBitmapPos = 0, 208;
HairColor = rgb16(144, 72, 0);
BeltColor = rgb16(72, 56, 16);
TotalVolume = 50000;
TotalSize = 100;
CanRead = true;
NameSingular = "axethrower dwarf";
NamePlural = "axethrower dwarves";
CanBeGenerated = true;
CreateDivineConfigurations = true;
IsAbstract = true;
/* Equipment initialization is overridden */
PanicLevel = 1;
Inventory == IRON meleeweapon(AXE) {Times = 6;}
FleshMaterial = DWARF_FLESH;
DeathMessage = "@Dd dies in agony.";
IgnoreDanger = true;
Frequency = 300;
HostileReplies == "\"In the name of @Gd I will slash you to pieces!\"";
AttachedGod = NONE;
UndeadVersions = false;
WieldedPosition = -1, -2;
FriendlyReplies =
{
4,
"\"Would you like me to teach you the best way to slice tomatoes?\"",
"@Dd shouts: \"Death to disbelievers!\"",
"@Dd praises @Gd with numerous hymns. @Pp is obviously a very devoted follower.",
"\"One day, Holy War will break out, hopefully I will earn my backpack by then!\"";
}
IsRangedAttacker = true;
KnownCWeaponSkills == AXES;
CWeaponSkillHits == 100;
RightSWeaponSkillHits = 50;
UsesLongArticle = true;
}

// In database.cpp:

template<> void databasecreator<character>::CreateDataBaseMemberMap()
{
...
ADD_MEMBER(IsRangedAttacker);
}

template<> void databasecreator<item>::CreateDataBaseMemberMap()
{
...
ADD_MEMBER(IsThrowingWeapon);
}

// In item.dat:

item
{
...
IsThrowingWeapon = false;
}

Config AXE;
{
...
IsThrowingWeapon = true;
}

Config DAGGER; // if you like throwing daggers :E
{
...
IsThrowingWeapon = true;
}

// In item.h:

struct itemdatabase : public databasebase
{
...
truth IsThrowingWeapon;
};

class item : public object
{
...
DATA_BASE_TRUTH(IsThrowingWeapon);
...
}

// In char.h:

struct characterdatabase : public databasebase
{
...
truth IsRangedAttacker;
};

class character : public entity, public id
{
public:
...
truth TryToAddToInventory(item*);
...
DATA_BASE_TRUTH(IsRangedAttacker);
...
#endif
...
truth CheckThrowItemOpportunity();
...
}

// In char.cpp

truth character::CheckForUsefulItemsOnGround(truth CheckFood)
{
...

for(uint c = 0; c < ItemVector.size(); ++c)
if(ItemVector[c]->CanBeSeenBy(this) && ItemVector[c]->IsPickable(this))
{
if(!(CommandFlags & DONT_CHANGE_EQUIPMENT)
&& TryToEquip(ItemVector[c]))
return true;

if(CheckFood && UsesNutrition() && !CheckIfSatiated()
&& TryToConsume(ItemVector[c]))
return true;

if( (ItemVector[c])->IsThrowingWeapon() && IsRangedAttacker()
&& TryToAddToInventory(ItemVector[c]))
return true;


}
return false;
}

truth character::TryToAddToInventory(item* Item)
{
if(!(GetBurdenState() > STRESSED)
|| !CanUseEquipment()
|| Item->GetSquaresUnder() != 1)
return false;

room* Room = GetRoom();

if(!Room || Room->PickupItem(this, Item, 1))
{
if(CanBeSeenByPlayer())
ADD_MESSAGE("%s picks up %s from the ground.", CHAR_NAME(DEFINITE), Item->CHAR_NAME(INDEFINITE));

Item->MoveTo(GetStack());
DexterityAction(5);
return true;
}

return false;
}


//finally, the algorithm itself

truth character::CheckThrowItemOpportunity()
{
if(!IsRangedAttacker() || !CanThrow() || !IsHumanoid() || !IsSmall() || !IsEnabled()) // total gum
return false;

// Steps:
// (1) - Acquire target as nearest enemy
// (2) - Check that this enemy is in range, and is in appropriate direction
// No friendly fire!
// (3) - check inventory for throwing weapon, select this weapon
// (4) - throw item in direction where the enemy is

//Check the visible area for hostiles
v2 Pos = GetPos();
v2 TestPos;
int RangeMax = GetLOSRange();
int CandidateDirections[7] = {0, 0, 0, 0, 0, 0, 0};
int HostileFound = 0;

for(int r = 1; r <= RangeMax; ++r)
{
for(int dir = 0; dir < 8; ++dir)
{
switch(dir)
{
case 0:
TestPos = v2(Pos.X - r, Pos.Y - r);
break;
case 1:
TestPos = v2(Pos.X, Pos.Y - r);
break;
case 2:
TestPos = v2(Pos.X + r, Pos.Y - r);
break;
case 3:
TestPos = v2(Pos.X - r, Pos.Y);
break;
case 4:
TestPos = v2(Pos.X + r, Pos.Y);
break;
case 5:
TestPos = v2(Pos.X - r, Pos.Y + r);
break;
case 6:
TestPos = v2(Pos.X, Pos.Y + r);
break;
case 7:
TestPos = v2(Pos.X + r, Pos.Y + r);
break;
}

level* Level = GetLevel();

if(Level->IsValidPos(TestPos))
{
square* TestSquare = GetNearSquare(TestPos);
character* Dude = TestSquare->GetCharacter();

if((Dude && Dude->IsEnabled() && (GetRelation(Dude) != HOSTILE)
&& Dude->CanBeSeenBy(this, false, true)))
{
CandidateDirections[dir] = BLOCKED;
}

if(Dude && Dude->IsEnabled() && (GetRelation(Dude) == HOSTILE)
&& Dude->CanBeSeenBy(this, false, true)
&& (CandidateDirections[dir] != BLOCKED))
{
//then load this candidate position direction into the vector of possible throw directions
CandidateDirections[dir] = SUCCESS;
HostileFound = 1;
}
}
}
}

int ThrowDirection = 0;
int TargetFound = 0;

if(HostileFound)
{
for(int dir = 0; dir < 8; ++dir)
{
if( (CandidateDirections[dir] == SUCCESS) && !TargetFound)
{
ThrowDirection = dir;
TargetFound = 1;
}
}
if(!TargetFound)
{
return false;
}
}
else
return false;

//check inventory for throwing weapon
itemvector ItemVector;
GetStack()->FillItemVector(ItemVector);
item* ToBeThrown = 0;

for(uint c = 0; c < ItemVector.size(); ++c)
if(ItemVector[c]->IsThrowingWeapon())
{
ToBeThrown = ItemVector[c];
break;
}

if(!ToBeThrown)
return false;

if(CanBeSeenByPlayer())
ADD_MESSAGE("%s throws %s.", CHAR_NAME(DEFINITE), ToBeThrown->CHAR_NAME(INDEFINITE));
ThrowItem(ThrowDirection, ToBeThrown);
EditExperience(ARM_STRENGTH, 75, 1 << 8);
EditExperience(DEXTERITY, 75, 1 << 8);
EditExperience(PERCEPTION, 75, 1 << 8);
EditNP(-50);
DexterityAction(5);
TerminateGoingTo();
return true;

}

// the end


 
 
View profile
Send message
Find posts Find topics
 
Feb 5, 2011 at 8:43 am #2  !
Zulox's Avatar
Zulox
gibberling


Joined: Apr 1, 2008
Occupation: Man-At-Arms
Location: Podolia
Interests: Swingin' mah blade
Posts: 78
You are a true HERO dear Sir, this piece of code does makes IVAN more complete.
 
 
View profile
Send message
Find posts Find topics
 
Feb 5, 2011 at 8:50 am #3  !
4zb4's Avatar
4zb4
archangel


Joined: Dec 11, 2008
Occupation: Not making sense
Location: The Gate
Interests: Magical Cooking!
Posts: 975
Groups:
We're most certainly lucky to have you Warheck.
If it works in LIVAN, it should theoretically work in IVAN CVS.
Also in relation to grenadier dwarves, you had best make them appear only around the time kamikaze dwarves or we'll be having mass amounts of "____ dissolved by mustard gas in Underwater Tunnel level 1"
 
image~Desuno!
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 5, 2011 at 5:57 pm #4  !
capristo's Avatar
capristo
The Imperialist


Joined: Dec 2, 2007
Location: New Attnam
Interests: bananas
Posts: 1227
Groups:
This sounds awesome!! Can't wait to try it. Dwarves throwing gas grenades, that's a scary thought.
 
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 1:33 am #5  !
chaostrom
Mage Prophet


Joined: Dec 3, 2007
Occupation: Standing between all life and death.
Posts: 2095
Groups:
Oh wow, this sounds awesome. You've even made it noob-friendly for those who can't code! A pineapple for you, sir!

 
image HEADBUTT
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 6, 2011 at 3:46 am #6  !
cowofdoom78963
kobold lord


Joined: Dec 15, 2010
Interests: mutant ass
Posts: 100
Hey, don't forget potions of acid! Those could be fun.
 
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 5:04 am #7  !
Warheck's Avatar
Warheck
kobold lord


Joined: Sep 9, 2010
Occupation: Petty Functionary
Location: Eating pea soup in the world map
Interests: Mangoes
Posts: 122
Groups:
Thank you all for your adulations. Yep. Potions, grenades, bones of Ullr. Heck, even AI instigated wand-zapping could be facilitated.
I attach here some photos of a dude being attacked by the axe-dwarf, and also of the dwarf picking up an axe from the ground. While the code probably isn't as streamlined as it could potentially be, it seems to work.
 



Attached Files
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 6, 2011 at 5:30 am #8  !
cowofdoom78963
kobold lord


Joined: Dec 15, 2010
Interests: mutant ass
Posts: 100
An axedwarf "of dulcis" seems kind of weird...
 
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 11:50 am #9  !
BDR's Avatar
BDR
archangel


Joined: Jan 11, 2008
Posts: 944
Is it any more sensible than a kamikaze dwarf of Silva?

Warheck: Good show, man. The idea of a grenade/poison/acid-chucker is a frightening thought, but well within the spirit of the game, as is the chucker of axes and daggers. In fact a dagger-thrower would be good to have; I don't usually use my run button a whole lot outside of maybe trying to train on the world map (when I do get around to playing anyway).
 
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 1:48 pm #10  !
Batman?
wolf


Joined: Dec 17, 2007
Occupation: Taking Names, Formerly Kicking Ass
Location: New Jersey
Posts: 217
Groups:
does it keep the monster from throwing its equippend weapon? because it could lead to a situation where a lot of enemies you would otherwise have a hard time with fighting your barehanded.

rondol throws his spear, it misses, rondol realizes he is fucked
 
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 3:53 pm #11  !
Somagu's Avatar
Somagu
He Who Scars


Joined: Dec 4, 2007
Occupation: Magical Pâtissier
Location: Lost Worlds
Interests: クッキングですの!
Posts: 824
Groups:

Batman? wrote   >

does it keep the monster from throwing its equippend weapon? because it could lead to a situation where a lot of enemies you would otherwise have a hard time with fighting your barehanded.

rondol throws his spear, it misses, rondol realizes he is fucked



Quote


- Has to be a ranged attacker (this is new)


I don't think that's a problem.

Aside from that, great googly moogly, Warheck, well done!
 
image
Proudly bringing disaster and mental scarring to Attnam since '05!
 
View profile
Send message
Find posts Find topics
 
Feb 6, 2011 at 8:04 pm #12  !
Warheck's Avatar
Warheck
kobold lord


Joined: Sep 9, 2010
Occupation: Petty Functionary
Location: Eating pea soup in the world map
Interests: Mangoes
Posts: 122
Groups:

Batman? wrote   >

does it keep the monster from throwing its equippend weapon? because it could lead to a situation where a lot of enemies you would otherwise have a hard time with fighting your barehanded.

rondol throws his spear, it misses, rondol realizes he is fucked



A good question. The thrower will only search his inventory for things that can be thrown, according to the GetStack() function. He will not throw his equipped weapons.
Furthermore, the spear would have to be IsThrowingWeapon = true; in the config in item.dat.
Heinously, the axedwarf will actually dual wield his two equipped axes to the bitter end.
 
 
View profile
Send message
Find posts Find topics
 
Feb 8, 2011 at 4:21 am #13  !
4zb4's Avatar
4zb4
archangel


Joined: Dec 11, 2008
Occupation: Not making sense
Location: The Gate
Interests: Magical Cooking!
Posts: 975
Groups:
I think someone needs to get working on a dwarven sub-dungeon (e.g. similar in length to the dragon cave, but dwarf themed)

Also I had this idea for "ninja smoke", which when it is released from dwarven gas grenades, creates a small puff of smoke and teleports the user away. I think I even did a bit of code (probably script actually) for it, i'll have to have a search.
With this and Warheck's work we could possibly make horribly annoying ninja dwarves.
 
image~Desuno!
 
View profile
Send message
Find posts Find topics
 
Feb 8, 2011 at 10:20 am #14  !
Warheck's Avatar
Warheck
kobold lord


Joined: Sep 9, 2010
Occupation: Petty Functionary
Location: Eating pea soup in the world map
Interests: Mangoes
Posts: 122
Groups:
They could throw shuriken. They could be ironic ninja dwarves, without all the stealth and subtlety.
I think a smoke cloud that teleports characters that step into it could be interesting.
Or a gas cloud that teleports itself around the level. Can smoke be teleported?
 
 
View profile
Send message
Find posts Find topics
 
Feb 8, 2011 at 7:00 pm #15  !
4zb4's Avatar
4zb4
archangel


Joined: Dec 11, 2008
Occupation: Not making sense
Location: The Gate
Interests: Magical Cooking!
Posts: 975
Groups:
Ironic ninja dwarves sounds exactly like something IVAN would have!
And I don't believe smoke can be teleported - but then again I've never tried it.
 
image~Desuno!
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 8, 2011 at 11:42 pm #16  !
cowofdoom78963
kobold lord


Joined: Dec 15, 2010
Interests: mutant ass
Posts: 100
You could just have the same effect as breaking a wand of teleport+create smoke.
 
 
View profile
Send message
Find posts Find topics
 
Feb 9, 2011 at 2:32 am #17  !
4zb4's Avatar
4zb4
archangel


Joined: Dec 11, 2008
Occupation: Not making sense
Location: The Gate
Interests: Magical Cooking!
Posts: 975
Groups:
IIRC the script I had used the "EFFECT_TELEPORT" (or whatever it is) under "Breathe effect" for the "NINJA_SMOKE" entry.
 
image~Desuno!
 
View profile
Send message
Find posts Find topics
 
Feb 15, 2011 at 4:23 am #18  !
Blob's Avatar
Blob
Master Drawey Person


Joined: Dec 4, 2007
Occupation: Computer Artist
Location: That's private. >:U
Interests: Drawing
Posts: 33
*stealth mode deactivated*
Warheck, you dont know me but please have some more adulation: this is awesome, keep it up.
*stealth mode activated*
 
 
View profile
Send message
Find posts Find topics
 
Feb 16, 2011 at 11:31 pm #19  !
slob's Avatar
slob
elder dark mage


Joined: Dec 3, 2007
Occupation: Big Daddy
Location: under the sheets with my sweety
Interests: Baby-makin'
Posts: 571
Hmmm. If the dwarves are aligned with gods, perhaps they could start with items aligned with that god in their inventory. E.g. wands to zap, items to throw, minimal chance of nice items. Why not make a new class of Kamikaze dwarf called rookie Kamikaze dwarf that carries a back pack but is afraid to use it and throws things only. Add in Elite Kamikaze dwarf that carries a backpack and will use it when he runs out of things to throw/zap and has a chance of carrying a nice item aligned with his god. Maybe the ultimate is the ninja Kamikaze dwarf that will disappear in a puff of smoke every time you get close enough to melee (like that bastard Izzy) and has all the elite Kamikaze dwarf abilities. You could make his ninja backpack a wand hybrid (probably by modifying wand code) have 5 teleport charges with only a local square effect when zapped (teleports only the wearer) and a major explosion when applied. Could be a formidable foe running around picking up wands and zapping you then teleporting out. You could also give him teleportitis and teleport control so that he could teleport more than just 5 times. Or adapt Blink dog code so that he could teleport at will. Maybe even make the backpacks aligned with the gods so that if you had a ninja backpack of loricatus and he was pissed at you and you tried to use it it would either explode or teleport away a random body part. As in "You zap the ninja backpack of loricatus. Somehow you feel Loricatus is angry. Your groin is teleported away. Suddenly you feel uncertain of your manhood. You die."
 
Last edited by slob : Feb 16, 2011 at 11:47 pm.
 
View profile
Send message
Find posts Find topics
 
Feb 17, 2011 at 9:56 am #20  !
Warheck's Avatar
Warheck
kobold lord


Joined: Sep 9, 2010
Occupation: Petty Functionary
Location: Eating pea soup in the world map
Interests: Mangoes
Posts: 122
Groups:

slob wrote   >

Maybe the ultimate is the ninja Kamikaze dwarf that will disappear in a puff of smoke every time you get close enough to melee (like that bastard Izzy) and has all the elite Kamikaze dwarf abilities.



I like this part. Why not have the ninja kamikaze dwarf disappear with a large explosion i.s.o. smoke, so that he teleports right before the explosion is triggered? He would then survive, and aligned god restocks his backpack right after. Evil eh?

I also like the idea of renaming the axedwarf as a Rookie Kamakaze dwarf who comes equipped with a backpack but refuses to use it, throwing objects instead. It develops that character's element of tragic desperation and it seems to fit better in light of the existing kamakaze dwarf heirarchy.

Aligned backpacks could also have different effects depending on your relation with the gods. If you were in really good standing (champion or 800+ say?) with Atavus, and applied his backpack, he could protect you from the ensuing explosion. On the other hand, if you were in normal or poor standing with Cruentus, and applied his backpack, then you would take damage as well as other bystanders. The size of the explosion could be proportional to the modulus of your relation with that god.
 
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 17, 2011 at 9:42 pm #21  !
cowofdoom78963
kobold lord


Joined: Dec 15, 2010
Interests: mutant ass
Posts: 100
rookie dwarves should die screaming instead of with a smile on their face.
 
 
View profile
Send message
Find posts Find topics
 
Feb 19, 2011 at 5:35 pm #22  !
Alveradok's Avatar
Alveradok
angel


Joined: Jan 25, 2008
Occupation: Turns out I can't have a cool avatar, I'll just put crap in it.
Location: 48kg / 105 lbs
Interests: My name is Failbert
Posts: 697
Groups:
Screaming "War is hell!" and other quotes.
 
Well I assume that a bolt has a given, numeric, amouunt of perwer. (assi in enegri)... unless it's LAERSER SKISKLS POEWN PEWN!
 
View profile
Send messageSend email
Find posts Find topics
 
Feb 28, 2011 at 8:22 pm #23  !
cowofdoom78963
kobold lord


Joined: Dec 15, 2010
Interests: mutant ass
Posts: 100
There should be some kind of named kamakazie dwarf. Like a grizzled kamakazie dwarf. He is spawned without any limbs and rolls around, and even though he rolls around he is incredibly fast, almost as fast as sherarax. He is pretty much immune to fire and carrys around tons of explosives. And if he runs out? No problem. He just summons up some more.
 
 
View profile
Send message
Find posts Find topics
 
Mar 1, 2011 at 1:10 am #24  !
chaostrom
Mage Prophet


Joined: Dec 3, 2007
Occupation: Standing between all life and death.
Posts: 2095
Groups:
If you don't have any arms you can't use explosives. Still, it's an awesome idea
 
image HEADBUTT
 
 Print


The Cathedral of Attnam  >  Programming  >  Coding the AI to throw items!!!

Jump to