void CoreScript::AddFlag(const Vector2I& _pos) { Vector2I pos = _pos; // A little UI fixup: set the flag to a porch // if we click on the switch. Chit* building = Context()->chitBag->QueryBuilding(IString(), pos, 0); if (building && (building->GetItem()->IName() == ISC::switchOn || building->GetItem()->IName() == ISC::switchOff)) { MapSpatialComponent* msc = GET_SUB_COMPONENT(building, SpatialComponent, MapSpatialComponent); if (msc) { pos = msc->PorchPos().min; } } Flag f = { pos, 0 }; if (flags.Find(f) < 0) { Chit* chit = Context()->chitBag->NewChit(); RenderComponent* rc = new RenderComponent("flag"); chit->Add(rc); ProcRenderInfo info; AssignProcedural(ISC::team, false, ParentChit()->GetItem()->ID(), ParentChit()->Team(), false, 0, 0, &info); rc->SetProcedural(0, info); chit->SetPosition(ToWorld3F(pos)); f.chitID = chit->ID(); flags.Push(f); } }
Chit* LumosChitBag::NewMonsterChit(const Vector3F& pos, const char* name, int team) { const ChitContext* context = Context(); Chit* chit = NewChit(); AddItem( name, chit, context->engine, team, 0 ); chit->Add( new RenderComponent( chit->GetItem()->ResourceName() )); chit->Add( new PathMoveComponent()); chit->Add( new AIComponent()); chit->SetPosition( pos ); chit->Add( new HealthComponent()); IString mob = chit->GetItem()->keyValues.GetIString(ISC::mob); if (ReserveBank::Instance()) { ReserveBank::Instance()->WithdrawMonster(chit->GetWallet(), mob == ISC::greater); } if (mob == ISC::greater) { // Mark this item as important with a destroyMsg: chit->GetItem()->SetSignificant(GetNewsHistory(), ToWorld2F(pos), NewsEvent::GREATER_MOB_CREATED, NewsEvent::GREATER_MOB_KILLED, 0); } chit->GetItem()->GetTraitsMutable()->Roll(chit->ID()); chit->GetItem()->FullHeal(); if (XenoAudio::Instance()) { XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos); } return chit; }
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 ); } }
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; }
void CoreScript::AssignToSquads() { // First, how many do we actually have? // Filter out everyone that has gone away. for (int i = 0; i < MAX_SQUADS; ++i) { //GL_ARRAY_FILTER(squads[i], (this->IsCitizen(ele))); squads[i].Filter(this, [](CoreScript* cs, int id) { return cs->IsCitizen(id); }); if (squads[i].Empty()) { // Flush out dead squads so they don't have // control flags laying around. waypoints[i].Clear(); } } int nSquaddies = 0; for (int i = 0; i < MAX_SQUADS; ++i) { nSquaddies += squads[i].Size(); } CChitArray recruits; int nCitizens = Citizens(&recruits); int nExpected = nCitizens - CITIZEN_BASE; if (nSquaddies >= nExpected) return; struct FilterData { CoreScript* cs; Chit* avatar;; }; FilterData fd = { this, Context()->chitBag->GetAvatar() }; // Filter to: not in squad AND not player controlled recruits.Filter(fd, [](const FilterData& ffd, Chit* chit) { return (ffd.cs->SquadID(chit->ID()) < 0 && chit != ffd.avatar); }); // Sort the best recruits to the end. // FIXME: better if there was a (working) power approximation recruits.Sort([](Chit* a, Chit* b) { const GameItem* itemA = a->GetItem(); const GameItem* itemB = b->GetItem(); int scoreA = itemA->Traits().Level() * (itemA->GetPersonality().Fighting() == Personality::LIKES ? 2 : 1); int scoreB = itemB->Traits().Level() * (itemB->GetPersonality().Fighting() == Personality::LIKES ? 2 : 1); // Reverse order. Best at end. return scoreA > scoreB; }); for (int n = nExpected - nSquaddies; n > 0; --n) { for (int i = 0; i < MAX_SQUADS; ++i) { if ( (squads[i].Size() < SQUAD_SIZE) && SquadAtRest(i)) { Chit* chit = recruits.Pop(); squads[i].Push(chit->ID()); ++nSquaddies; break; } } } }