예제 #1
0
void LumosChitBag::HandleBolt( const Bolt& bolt, const ModelVoxel& mv )
{
	const ChitContext* context = Context();
	Chit* chitShooter = GetChit( bolt.chitID );	// may be null
	int shooterTeam = -1;
	if ( chitShooter && chitShooter->GetItemComponent() ) {
		shooterTeam = chitShooter->GetItemComponent()->GetItem()->Team();
	}
	int explosive = bolt.effect & GameItem::EFFECT_EXPLOSIVE;
 
	if ( !explosive ) {
		if ( mv.Hit() ) {
			Chit* chitHit = mv.ModelHit() ? mv.model->userData : 0;
			DamageDesc dd( bolt.damage, bolt.effect );

			if ( chitHit ) {
				GLASSERT( GetChit( chitHit->ID() ) == chitHit );
				if ( chitHit->GetItemComponent() &&
					 chitHit->GetItemComponent()->GetItem()->Team() == shooterTeam ) 
				{
					// do nothing. don't shoot own team.
				}
				else {
		
					ChitDamageInfo info( dd );
					info.originID = bolt.chitID;
					info.awardXP  = true;
					info.isMelee  = false;
					info.isExplosion = false;
					info.originOfImpact = mv.at;

					ChitMsg msg( ChitMsg::CHIT_DAMAGE, 0, &info );
					chitHit->SendMessage( msg, 0 );
				}
			}
			else if ( mv.VoxelHit() ) {
				context->worldMap->VoxelHit( mv.voxel, dd );
			}
		}
	}
	else {
		// How it used to work. Now only uses radius:
			// Here don't worry about the chit hit. Just ray cast to see
			// who is in range of the explosion and takes damage.
		
			// Back up the origin of the bolt just a bit, so it doesn't keep
			// intersecting the model it hit. Then do ray checks around to 
			// see what gets hit by the explosion.

		float rewind = Min( 0.1f, 0.5f*bolt.len );
		GLASSERT( Equal( bolt.dir.Length(), 1.f, 0.001f ));
		Vector3F origin = mv.at - bolt.dir * rewind;

		DamageDesc dd( bolt.damage, bolt.effect );
		BattleMechanics::GenerateExplosion( dd, origin, bolt.chitID, context->engine, this, context->worldMap );
	}
}
예제 #2
0
int CoreScript::CorePower()
{
	int power = 0;
	for (int i = 0; i < citizens.Size(); ++i) {
		Chit* chit = Context()->chitBag->GetChit(citizens[i]);
		if (chit && chit->GetItemComponent()) {
			power += chit->GetItemComponent()->PowerRating(true);
		}
	}
	return power;
}
예제 #3
0
Chit* LumosChitBag::NewBadGuy(const grinliz::Vector2I& pos, 
							  const IString& name, 
							  const grinliz::IString& type, 
							  int team, int level )
{
	const ChitContext* context = Context();
	Chit* chit = NewChit();
	const GameItem& root = ItemDefDB::Instance()->Get(type.safe_str());

	chit->Add( new RenderComponent(root.ResourceName()));
	chit->Add( new PathMoveComponent());
	AddItem(root.Name(), chit, context->engine, team, level, 0, "human");

	ReserveBank::Instance()->WithdrawMonster(chit->GetWallet(), true);
	chit->GetItem()->GetTraitsMutable()->Roll( random.Rand() );
	chit->GetItem()->GetPersonalityMutable()->Roll( random.Rand(), &chit->GetItem()->Traits() );
	chit->GetItem()->FullHeal();

	chit->GetItem()->SetProperName(name);

	AIComponent* ai = new AIComponent();
	chit->Add( ai );

	chit->Add( new HealthComponent());
	chit->SetPosition( (float)pos.x+0.5f, 0, (float)pos.y+0.5f );

	for (int i = 0; i < ForgeScript::NUM_ITEM_TYPES; ++i) {
		ForgeScript::ForgeData forgeData;
		forgeData.type = i;
		forgeData.subType = 0;
		forgeData.tech = 3;
		forgeData.level = level;
		forgeData.team = team;
		int seed = random.Rand();
		ForgeScript::BestSubItem(&forgeData, seed);

		TransactAmt cost;
		TransactAmt freeCreate;
		static const int CRYSTAL[NUM_CRYSTAL_TYPES] = { 3, 2, 1, 1 };
		freeCreate.Set(0, CRYSTAL);

		GameItem* loot = ForgeScript::ForgeRandomItem(forgeData, freeCreate, &cost, seed, ReserveBank::GetWallet());
		if (loot) {
			chit->GetItemComponent()->AddToInventory(loot);
			loot->SetSignificant(chit->Context()->chitBag->GetNewsHistory(), 
								 ToWorld2F(chit->Position()),
								 NewsEvent::FORGED, NewsEvent::UN_FORGED, chit->GetItem());
		}
	}

	chit->GetItem()->SetSignificant(GetNewsHistory(), ToWorld2F(pos), NewsEvent::DENIZEN_CREATED, NewsEvent::DENIZEN_KILLED, 0);

	if (XenoAudio::Instance()) {
		Vector3F pos3 = ToWorld3F(pos);
		XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3);
	}
	return chit;
}
예제 #4
0
void CoreScript::DoStrategicTick()
{
	// Look around for someone to attack. They should be:
	//	- someone we have a negative attitude about (accounts for lots of things)
	//	- weaker overall
	//
	// We should:
	//	- have a reasonably armed squad

	bool squadReady[MAX_SQUADS] = { false };
	CChitArray squaddies;
	
	// Check for ready squads.
	for (int i = 0; i < MAX_SQUADS; ++i) {
		this->Squaddies(i, &squaddies);
		if (squaddies.Size() < SQUAD_SIZE) 
			continue;
		if (!SquadAtRest(i))
			continue;

		// Do we have enough guns? Seems to be
		// the best / easiest metric.

		int nGuns = 0;
		for (int k = 0; k < squaddies.Size(); ++k) {
			Chit* chit = squaddies[k];
			ItemComponent* ic = chit->GetItemComponent();
			if (   chit->GetItem() 
				&& chit->GetItem()->HPFraction() > 0.75f 
				&& ic 
				&& ic->QuerySelectRanged()) 
			{
				nGuns++;
			}
		}
		squadReady[i] = nGuns >= SQUAD_SIZE - 1;
	}

	int nReady = 0;
	for (int i = 0; i < MAX_SQUADS; ++i) {
		if (squadReady[i])
			++nReady;
	}

	Sim* sim = Context()->chitBag->GetSim();
	GLASSERT(sim);
	if (!sim) return;

	Vector2I sector = ToSector(ParentChit()->Position());
	CCoreArray stateArr;
	sim->CalcStrategicRelationships(sector, 3, &stateArr);

	// The strategic relationships need to be calculated, but after that,
	// there's no point in computing further if we don't have a squad to 
	// send into action.
	if (nReady == 0) 
		return;

	int myPower = this->CorePower();

	CoreScript* target = 0;
	for (int i = 0; i < stateArr.Size(); ++i) {
		CoreScript* cs = stateArr[i];
		if (cs->NumTemples() == 0)		// Ignore starting out domains so it isn't a complete wasteland out there.
			continue;

		if (   Team::Instance()->GetRelationship(cs->ParentChit(), this->ParentChit()) == ERelate::ENEMY		// Are we enemies at the diplomatic level
			&& Team::Instance()->Attitude(this, cs) < 0)														// Does 'this' have a negative attitude to the other?
		{
			int power = cs->CorePower();
			if (power < myPower * 0.75f) {
				// Assuming this is actually so rare that it doesn't matter to select the best.
				target = cs;
				break;
			}
		}
	}

	if (!target) return;

	// Attack!!!
	bool first = true;
	Vector2F targetCorePos2 = ToWorld2F(target->ParentChit()->Position());
	Vector2I targetCorePos = ToWorld2I(target->ParentChit()->Position());;
	Vector2I targetSector = ToSector(targetCorePos);

	for (int i = 0; i < MAX_SQUADS; ++i) {
		if (!squadReady[i]) continue;

		Vector2I pos = { 0, 0 };
		pos = targetCorePos;
		if (first) {
			first = false;
		}
		else {
			BuildingWithPorchFilter filter;
			Chit* building = Context()->chitBag->FindBuilding(IString(), targetSector, &targetCorePos2, LumosChitBag::EFindMode::RANDOM_NEAR, 0, &filter);
			if (building) {
				pos = ToWorld2I(building->Position());
			}
		}
		GLASSERT(!pos.IsZero());
		this->SetWaypoints(i, pos);
	}
}