Search Results
Searched for posts by fejoa in all forums

Showing results 991 - 1000 out of 1011 total
Modify your search
Posted by fejoa, Feb 12, 2011 at 3:32 am
Inlux is an anagram of linux
Posted by fejoa, Feb 8, 2011 at 6:20 am
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?
Posted by fejoa, Feb 6, 2011 at 4:04 pm
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.
Posted by fejoa, Feb 6, 2011 at 1:04 am
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.
Posted by fejoa, Feb 5, 2011 at 4:03 am
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:

[color=#9acd32]// To make the AI throw items, add the following lines of code:

// In human.h:[/color]

CHARACTER(humanoid, character)
{
	public:
	...
	[b]virtual truth CheckThrowItemOpportunity();[/b]
	...
}

[b]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; }
};[/b]

[color=#9acd32]// In human.cpp:[/color]
[b]
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();
}

[/b]
[color=#9acd32]// In char.dat:[/color]

character
{
	...
	[b]IsRangedAttacker = false;[/b]
}

[b]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;
}
[/b]
[color=#9acd32]// In database.cpp:[/color]

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

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

[color=#9acd32]// In item.dat:[/color]

item
{
	...
	[b]IsThrowingWeapon = false;[/b]
}

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

[color=#9acd32]// In item.h:[/color]

struct itemdatabase : public databasebase
{
	...
	[b]truth IsThrowingWeapon;[/b]
};

class item : public object
{
	...
	[b]DATA_BASE_TRUTH(IsThrowingWeapon);[/b]
	...
}

[color=#9acd32]// In char.h:[/color]

struct characterdatabase : public databasebase
{
	...
	[b]truth IsRangedAttacker;[/b]
};

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

[color=#9acd32]// In char.cpp[/color]

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;
[b]
			if( (ItemVector[c])->IsThrowingWeapon() && IsRangedAttacker() 
				&& TryToAddToInventory(ItemVector[c]))
				return true; [/b]

    }
  return false;
}
[b]
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;
}
[/b]

[color=#9acd32]//finally, the algorithm itself[/color]
[b]
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;
	
}
[/b]
[color=#9acd32]// the end[/color]

Posted by fejoa, Jan 25, 2011 at 5:20 am
That's true, Zulox and 4zb4 make good points about the value of mustard gas. I have often had mustard gas grenades explode on me early on in the game and hated it because it would pretty well annihilate my character. It seems like mustard gas is the kind of thing to stockpile carefully for use later on against roomfuls of nasties.
Posted by fejoa, Jan 13, 2011 at 9:12 pm
4zb4 wrote
So far i've gotten by simply by cutting/copying pixels of the appropriate colours and moving them to form what I want

I did things in this way for a time too, 4zb4. I was terribly confused about the arrangement of the colour index until I finally found all the relevant pieces of information and compiled the document.
Posted by fejoa, Jan 11, 2011 at 6:19 pm
I gazed upon the IVAN sourceforge page and lo, I saw a curious explosion in the number of downloads
Posted by fejoa, Jan 11, 2011 at 3:00 am
ZAP!
Here is that thing you've always wanted, it's a document about IVAN's quirky graphics.
Attached files
IVAN_graphics.pdf ()
Posted by fejoa, Jan 9, 2011 at 9:57 pm
I always notice the slave is capable of carrying a surprising amount of equipment, he takes a lot before he gets burdened. He must have more leg-strength in that case. A stethoscope should help us get to the bottom of this.