Пример #1
0
Chit* LumosChitBag::NewDenizen( const grinliz::Vector2I& pos, int team )
{
	const ChitContext* context = Context();
	IString itemName;

	switch (Team::Group(team)) {
		case TEAM_HOUSE:	itemName = (random.Bit()) ? ISC::humanFemale : ISC::humanMale;	break;
		case TEAM_GOB:		itemName = ISC::gobman;											break;
		case TEAM_KAMAKIRI:	itemName = ISC::kamakiri;										break;
		default: GLASSERT(0); break;
	}

	Chit* chit = NewChit();
	const GameItem& root = ItemDefDB::Instance()->Get(itemName.safe_str());

	chit->Add( new RenderComponent(root.ResourceName()));
	chit->Add( new PathMoveComponent());

	const char* altName = 0;
	if (Team::Group(team) == TEAM_HOUSE) {
		altName = "human";
	}
	AddItem(root.Name(), chit, context->engine, team, 0, 0, altName);

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

	IString nameGen = chit->GetItem()->keyValues.GetIString( "nameGen" );
	if ( !nameGen.empty() ) {
		LumosChitBag* chitBag = chit->Context()->chitBag;
		if ( chitBag ) {
			chit->GetItem()->SetProperName(chitBag->NameGen(nameGen.c_str(), chit->ID()));
		}
	}

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

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

	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;
}
Пример #2
0
bool MOBKeyFilter::Accept(Chit* chit)
{
	GameItem* item = chit->GetItem();
	if (item) {
		IString mob = item->keyValues.GetIString(ISC::mob);
		if (!mob.empty()) {
			if (value.empty())
				return RelationshipFilter::Accept(chit);
			else if (value == mob)
				return RelationshipFilter::Accept(chit);
		}
	}
	return false;
}
Пример #3
0
Chit* LumosChitBag::NewLawnOrnament(const Vector2I& pos, const char* name, int team)
{
	const ChitContext* context = Context();
	Chit* chit = NewChit();

	GameItem* rootItem = ItemDefDB::Instance()->Get(name).Clone();

	// Hack...how to do this better??
	if (rootItem->IResourceName() == "ruins1.0") {
		CStr<32> str;
		str.Format("ruins1.%d", random.Rand(2));
		rootItem->SetResource(str.c_str());
	}

	int size = 1;
	rootItem->keyValues.Get(ISC::size, &size);

	MapSpatialComponent* msc = new MapSpatialComponent();
	msc->SetBuilding(size, false, 0);
	msc->SetBlocks((rootItem->flags & GameItem::PATH_NON_BLOCKING) ? false : true);
	chit->Add(msc);
	MapSpatialComponent::SetMapPosition(chit, pos.x, pos.y);


	chit->Add(new RenderComponent(rootItem->ResourceName()));
	chit->Add(new HealthComponent());
	AddItem(rootItem, chit, context->engine, team, 0);

	IString proc = rootItem->keyValues.GetIString("procedural");
	if (!proc.empty()) {
		ProcRenderInfo info;
		AssignProcedural(chit->GetItem(), &info);
		chit->GetRenderComponent()->SetProcedural(0, info);
	}
	
	context->engine->particleSystem->EmitPD(ISC::constructiondone, ToWorld3F(pos), V3F_UP, 0);

	if (XenoAudio::Instance()) {
		Vector3F pos3 = ToWorld3F(pos);
		XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3);
	}

	return chit;
}
Пример #4
0
void CoreScript::DoTickNeutral( int delta, int nSpawnTicks )
{
	int lesser, greater, denizen;
	const Census& census = Context()->chitBag->census;
	census.NumByType(&lesser, &greater, &denizen);

	IString defaultSpawn = Context()->worldMap->GetSectorData(sector).defaultSpawn;
	int typical = 0;
	int numOf = census.NumOf(defaultSpawn, &typical);

	bool lesserPossible = (lesser < TYPICAL_LESSER) && (!typical || numOf < typical * 2);

	Vector2I pos2i = ToWorld2I(parentChit->Position());
	Vector2I sector = ToSector(pos2i);

	if (nSpawnTicks && lesserPossible) {
#if SPAWN_MOBS > 0
		int spawnEnabled = Context()->chitBag->GetSim()->SpawnEnabled() & Sim::SPAWN_LESSER;

		if (Context()->chitBag->GetSim() && spawnEnabled && !defaultSpawn.empty()) {

			Vector3F pf = { (float)pos2i.x + 0.5f, 0, (float)pos2i.y + 0.5f };
			int nSpawn = (defaultSpawn == ISC::trilobyte) ? 4 : 1;

			int team = Team::GetTeam(defaultSpawn);
			GLASSERT(team != TEAM_NEUTRAL);
			for (int i = 0; i < nSpawn; ++i) {
				Context()->chitBag->NewMonsterChit(pf, defaultSpawn.safe_str(), team);
				pf.x += 0.05f;
			}
		}
#endif
	}
	// Clear the work queue - chit is gone that controls this.
	if (!workQueue || workQueue->HasJob()) {
		delete workQueue;
		workQueue = new WorkQueue();
		workQueue->InitSector(parentChit, ToSector(parentChit->Position()));
	}
}
Пример #5
0
void NewsEvent::Console(GLString* str, ChitBag* chitBag, int shortNameID) const
{
	*str = "";
	Vector2I sector = ToSector(ToWorld2I(pos));

	const GameItem* first  = ItemDB::Instance()->Active(firstItemID);
//	const GameItem* second = ItemDB::Instance()->Active(secondItemID);

	IString firstName  = IDToName(firstItemID,  firstItemID == shortNameID);
	IString secondName = IDToName(secondItemID, secondItemID == shortNameID);
	if (firstName.empty())  firstName  = StringPool::Intern("[unknown]");
	if (secondName.empty()) secondName = StringPool::Intern("[unknown]");

	float age = float(double(date) / double(AGE_IN_MSEC));
	IString domain;
	if (chitBag->Context()->worldMap) {
		const SectorData& sd = chitBag->Context()->worldMap->GetSectorData(sector);
		domain = sd.name;
	}

	IString firstTeamName  = Team::IsCoreController(firstTeam) ? Team::Instance()->TeamName(firstTeam) : IString();
	IString secondTeamName = Team::IsCoreController(secondTeam) ? Team::Instance()->TeamName(secondTeam) : IString();

	switch (what) {
		case DENIZEN_CREATED:
		str->Format("%.2f: Denizen %s " MOB_created " at %s with %s.", age, 
					firstName.c_str(), domain.safe_str(), firstTeamName.safe_str());
		break;

		case DENIZEN_KILLED:
		str->Format("%.2f: Denizen %s (%s) " MOB_destroyed " at %s by %s.", age, 
					firstName.safe_str(), 
					Team::IsRogue(firstTeam) ? "rogue" : firstTeamName.safe_str(), 
					domain.safe_str(), secondName.safe_str());
		break;

		case GREATER_MOB_CREATED:
		// They get created at the center, then sent. So the domain is meaningless.
		str->Format("%.2f: %s " MOB_created ".", age, firstName.safe_str());
		break;

		case DOMAIN_CREATED:
		// "taken over" is interesting; a domain getting created is not.
		*str = "";
		break;

		case ROGUE_DENIZEN_JOINS_TEAM:
		str->Format("%.2f: Rogue Denizen %s joins at %s with %s.", age, 
					firstName.safe_str(), domain.safe_str(), firstTeamName.safe_str() );
		break;

		case GREATER_MOB_KILLED:
		str->Format("%.2f: %s " MOB_destroyed " at %s by %s.", age, 
					firstName.safe_str(), domain.safe_str(), secondName.safe_str());
		break;

		case DOMAIN_DESTROYED:
		GLASSERT(firstTeam);	// how is a neutral destroyed??
		str->Format("%.2f: %s domain %s " MOB_destroyed " by %s.", age, 
					firstTeamName.safe_str(), domain.safe_str(), secondName.safe_str());
		break;

		// Neutral domains are taken over.
		// Subdomains are conquored.
		case DOMAIN_TAKEOVER:
		str->Format("%.2f: %s occupied by %s.", age, domain.safe_str(), firstTeamName.safe_str());
		break;

		case DOMAIN_CONQUER:
		str->Format("%.2f: %s is conquered by %s.", age, domain.safe_str(), firstTeamName.safe_str() );
		break;

		case SUPERTEAM_DELETED:
		GLASSERT(firstTeam);
		str->Format("%.2f: %s super domain %s " MOB_destroyed ". Sub-domains are now self controlled.", age, firstTeamName.safe_str(), domain.safe_str());
		break;

		case SUBTEAM_DELETED:
		GLASSERT(firstTeam);
		GLASSERT(secondTeam);
		str->Format("%.2f: %s no longer controlled by %s.", age, firstTeamName.safe_str(), secondTeamName.safe_str());
		break;

		case FORGED:
		str->Format("%.2f: %s forged %s at %s.", age, secondName.safe_str(), firstName.c_str(), domain.safe_str());
		break;

		case UN_FORGED:
		str->Format("%.2f: %s " MOB_destroyed " %s at %s.", age, secondName.c_str(), firstName.c_str(), domain.c_str());
		break;

		case PURCHASED:
		if (first) {
			str->Format("%.2f: %s purchased %s at %s for %d (%d tax).", age, secondName.c_str(), firstName.c_str(), domain.c_str(),
						first->GetValue(), int(first->GetValue() * SALES_TAX));
		}
		else {
			str->Format("%.2f: %s purchased %s at %s.", age, secondName.c_str(), firstName.c_str(), domain.c_str());
		}
		break;

		case STARVATION:
		str->Format("%.2f: %s has been overcome by starvation at %s.", age, firstName.c_str(), domain.c_str());
		break;

		case BLOOD_RAGE:
		str->Format("%.2f: a distraught %s is overcome by blood rage at %s.", age, firstName.c_str(), domain.c_str());
		break;

		case VISION_QUEST:
		str->Format("%.2f: %s is consumed by despair at %s and leaves for a vision quest.", age, firstName.c_str(), domain.c_str());
		break;

		case GREATER_SUMMON_TECH:
		str->Format("%.2f: %s is called to %s by the siren song of Tech.", age, firstName.c_str(), domain.c_str());
		break;

		case ATTITUDE_FRIEND:
		str->Format("%.2f: %s sees %s with friendly intent.", age, firstName.safe_str(), secondName.safe_str());
		break;

		case ATTITUDE_NEUTRAL:
		str->Format("%.2f: %s sees %s with neutral regard.", age, firstName.safe_str(), secondName.safe_str());
		break;

		case ATTITUDE_ENEMY:
		str->Format("%.2f: %s sees %s as an enemy.", age, firstName.safe_str(), secondName.safe_str());
		break;

		default:
		GLASSERT(0);
	}
}
Пример #6
0
Chit* LumosChitBag::NewBuilding(const Vector2I& pos, const char* name, int team)
{
	const ChitContext* context = Context();
	Chit* chit = NewChit();

	const GameItem& rootItem = ItemDefDB::Instance()->Get(name);
	GameItem* item = rootItem.Clone();

	// Hack...how to do this better??
	if (item->IResourceName() == "pyramid0") {
		CStr<32> str;
		str.Format("pyramid%d", random.Rand(3));
		item->SetResource(str.c_str());
	}
	if (item->IResourceName() == ISC::kiosk) {
		switch (random.Rand(4)) {
			case 0: item->SetResource("kiosk.n");	break;
			case 1: item->SetResource("kiosk.m");	break;
			case 2: item->SetResource("kiosk.s");	break;
			default:item->SetResource("kiosk.c");	break;
		}
	}

	int size = 1;
	rootItem.keyValues.Get(ISC::size, &size);
	int porch = 0;
	rootItem.keyValues.Get(ISC::porch, &porch);
	const int circuit = 0;

	// Should be pre-cleared. But recover from weird situations by clearing.
	// Note that water is a real problem.
	Rectangle2I r;
	r.Set(pos.x, pos.y, pos.x + size - 1, pos.y + size - 1);
	for (Rectangle2IIterator it(r); !it.Done(); it.Next()) {
		const WorldGrid& wg = context->worldMap->GetWorldGrid(it.Pos());
		GLASSERT(wg.IsLand());
		(void)wg;
		context->worldMap->SetRock(it.Pos().x, it.Pos().y, 0, false, 0);
		context->worldMap->SetPlant(it.Pos().x, it.Pos().y, 0, 0);
	}

	MapSpatialComponent* msc = new MapSpatialComponent();
	msc->SetBuilding(size, porch != 0, circuit);
	msc->SetBlocks((rootItem.flags & GameItem::PATH_NON_BLOCKING) ? false : true);
	chit->Add(msc);
	MapSpatialComponent::SetMapPosition(chit, pos.x, pos.y);

	chit->Add(new RenderComponent(item->ResourceName()));
	chit->Add(new HealthComponent());
	AddItem(item, chit, context->engine, team, 0);

	IString script = rootItem.keyValues.GetIString("script");
	if (!script.empty()) {
		Component* s = ComponentFactory::Factory(script.c_str(), &chitContext);
		GLASSERT(s);
		chit->Add(s);
	}

	IString proc = rootItem.keyValues.GetIString("procedural");
	if (!proc.empty()) {
		ProcRenderInfo info;
		AssignProcedural(chit->GetItem(), &info);
		chit->GetRenderComponent()->SetProcedural(0, info);
	}

	IString consumes = rootItem.keyValues.GetIString(ISC::zone);
	if (!consumes.empty()) {
		Component* s = ComponentFactory::Factory("EvalBuildingScript", &chitContext);
		GLASSERT(s);
		chit->Add(s);
	}

	IString nameGen = rootItem.keyValues.GetIString( "nameGen");
	if ( !nameGen.empty() ) {
		IString p = Context()->chitBag->NameGen(nameGen.c_str(), chit->random.Rand());
		chit->GetItem()->SetProperName( p );
	}

#if 0	// debugging
	SectorPort sp;
	sp.sector.Set( pos.x/SECTOR_SIZE, pos.y/SECTOR_SIZE );
	sp.port = 1;
	worldMap->SetRandomPort( sp );
#endif

	context->engine->particleSystem->EmitPD( ISC::constructiondone, ToWorld3F( pos ), V3F_UP, 0 );

	if (XenoAudio::Instance()) {
		Vector3F pos3 = ToWorld3F(pos);
		XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3);
	}

	return chit;
}
Пример #7
0
double EvalBuildingScript::EvalIndustrial( bool debugLog )
{
	Chit* building = ParentChit();

	int hitB = 0, hitIBuilding = 0, hitNBuilding = 0, hitWater = 0, hitPlant = 0, hitRock = 0, hitWaterfall = 0;
	int hitShrub = 0;	// doesn't terminate a ray.


	if (lastEval == 0 || (Context()->chitBag->AbsTime() - lastEval) > 2000) {
		lastEval = Context()->chitBag->AbsTime();

		GameItem* item = building->GetItem();
		GLASSERT(item);
		reachable = true;

		IString consume = item->keyValues.GetIString(ISC::zone);
		if (consume.empty()) {
			eval = 0;
			return eval;
		}
		MapSpatialComponent* msc = GET_SUB_COMPONENT(building, SpatialComponent, MapSpatialComponent);
		GLASSERT(msc);
		if (!msc) {
			eval = 0;
			return eval;
		}
		Rectangle2I porch = msc->PorchPos();

		static const int RAD = 4;

		Rectangle2I bounds = porch;
		if (porch.min.x == 0) {	// shouldn't happen, but be sure.
			GLASSERT(0);
			eval = 0;
			return eval;	
		}

		bounds.Outset(RAD);
		Vector2I sector = ToSector(building->Position());

		WorldMap* worldMap = Context()->worldMap;
		Rectangle2I mapBounds = worldMap->Bounds();
		if (!mapBounds.Contains(bounds)) {
			eval = 0;
			return eval;	// not worth dealing with edge of world
		}

		// Check if we can go from the core to the porch.
		// And make sure the core is inUse!
		CoreScript* cs = CoreScript::GetCore(ToSector(porch.min));
		if (!cs || !cs->InUse())
			reachable = false;
		if (reachable) {
			const SectorData& sd = worldMap->GetSectorData(ToSector(porch.min));
			reachable = worldMap->CalcPath(ToWorld2F(sd.core), ToWorld2F(porch.min), 0, 0, false);
		}

		CChitArray arr;
		BuildingFilter buildingFilter;

		const FluidSim* fluidSim = Context()->physicsSims->GetFluidSim(sector);
		bool hasWaterfalls = fluidSim->NumWaterfalls() > 0;

		LumosChitBag* chitBag = Context()->chitBag;
		Rectangle2IEdgeIterator it(bounds);

		while (!it.Done()) {
			Vector2I pos = { it.Pos().x >= porch.max.x ? porch.max.x : porch.min.x,
							 it.Pos().y >= porch.max.y ? porch.max.y : porch.min.y };

			LineWalk walk(pos.x, pos.y, it.Pos().x, it.Pos().y);
			walk.Step();	// ignore where we are standing.

			while ( !walk.Done() ) {	// non-intuitive iterator. See linewalk docs.
				// - building
				// - plant
				// - ice
				// - rock
				// - waterfall
				// - water

				// Buildings. Can be 2x2. Extend out beyond current check.
				bool hitBuilding = false;
				Vector2I p = walk.P();
				// Don't count self as a hit, but stops the ray cast.
				// Also, use a larger radius because buildings can be 2x2
				chitBag->QuerySpatialHash(&arr, ToWorld2F(p), 0.8f, 0, &buildingFilter);
				for (int i = 0; i < arr.Size(); ++i) {
					if (arr[i] != building) {
						MapSpatialComponent* buildingMSC = GET_SUB_COMPONENT(arr[i], SpatialComponent, MapSpatialComponent);
						GLASSERT(buildingMSC);
						if (buildingMSC->Bounds().Contains(p)) {
							hitBuilding = true;
							double thisSys = arr[i]->GetItem()->GetBuildingIndustrial();

							hitB++;
							if (thisSys <= -0.5) hitNBuilding++;
							if (thisSys >= 0.5)  hitIBuilding++;

							break;
						}
					}
				}
				if (hitBuilding) break;
				
				const WorldGrid& wg = worldMap->GetWorldGrid(p.x, p.y);
				if (wg.Plant()) {
//					int type = wg.Plant() - 1;
					int stage = wg.PlantStage();

					if (stage >= 2) {
						++hitPlant;
						break;
					}
					else {
						hitShrub++;
					}
				}

				if (wg.RockHeight()) {
					++hitRock;
					break;
				}
				if (wg.IsWater()) {
					++hitWater;
					break;
				}

				Rectangle2I wb;
				wb.min = wb.max = p;
				if (hasWaterfalls && fluidSim->ContainsWaterfalls(wb)) {
					++hitWaterfall;
					break;
				}
				walk.Step();
			}
			it.Next();
		}

		// Note rock/ice isn't counted either way.
		int natural = hitNBuilding
			+ hitWater
			+ hitPlant
			+ 10 * hitWaterfall
			+ hitShrub / 4;				// small plants don't add to rRays, so divide is okay.
		int industrial = hitIBuilding;
		int nRays = hitNBuilding + hitWater + hitPlant + hitWaterfall + hitIBuilding;

		eval = 0;
		if (nRays) {
			// With this system, that one ray (say from a distillery to plant) can be
			// hugely impactful. This may need tweaking:
			if (nRays < 2)
				nRays = 2;
			eval = double(industrial - natural) / double(nRays);
		}
		eval = Clamp(eval, -1.0, 1.0);

		if (debugLog) {
			Vector2I pos = ToWorld2I(building->Position());
			GLOUTPUT(("Building %s at %d,%d eval=%.2f nRays=%d \n  hit: Build=%d (I=%d N=%d) water=%d plant=%d rock=%d\n",
				building->GetItem()->Name(),
				pos.x, pos.y,
				eval,
				nRays,
				hitB, hitIBuilding, hitNBuilding, hitWater, hitPlant, hitRock));
			(void)pos;
		}
	}
	return eval;
}