rendered paste bodyIndex: ScriptMgr.cpp===================================================================--- ScriptMgr.cpp (revision 136)+++ ScriptMgr.cpp (working copy)@@ -393,6 +393,7 @@ //Wailing caverns //Western plaguelands //Westfall+extern void AddSC_npc_DaphneStillwell(); //Wetlands //Winterspring //Zangramarsh@@ -782,6 +783,7 @@ //Wailing caverns //Western plaguelands //Westfall+ AddSC_npc_DaphneStillwell(); //Wetlands //Winterspring //ZangramarshIndex: scripts/creature/EventAI.cpp===================================================================--- scripts/creature/EventAI.cpp (revision 0)+++ scripts/creature/EventAI.cpp (revision 0)@@ -0,0 +1,374 @@+/* Copyright (C) 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>+* This program is free software; you can redistribute it and/or modify+* it under the terms of the GNU General Public License as published by+* the Free Software Foundation; either version 2 of the License, or+* (at your option) any later version.+*+* This program is distributed in the hope that it will be useful,+* but WITHOUT ANY WARRANTY; without even the implied warranty of+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+* GNU General Public License for more details.+*+* You should have received a copy of the GNU General Public License+* along with this program; if not, write to the Free Software+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+*/++#include "EventAI.h"+#include "../../../../shared/WorldPacket.h"+#include "../../../../game/GameObject.h"+#include "../../../../game/TargetedMovementGenerator.h"++void ScriptedEvent::Talk(char *txt, uint32 Type, uint32 snd, uint8 lang)+{+ text_data = txt; data1 = snd; data2 = lang; data3 = Type ;+ type = 1;+}++void ScriptedEvent::Waypoint(float X, float Y, float Z, float O, bool run)+{+ x = X; y = Y; z = Z; o = O; data1 = run;+ type = 2;+}+++void ScriptedEvent::Emote(uint32 emo, bool State)+{+ data1 = emo; data2 = State;+ type = 3;+}++void ScriptedEvent::Summon(uint32 id, uint32 type, uint32 despawn, float X, float Y, float Z, float O)+{+ data1 = id; x = X; y = Y; z = Z; o = O;+ type = 4;+}++void ScriptedEvent::Cast(uint32 id, Object *tar, uint32 triggered)+{+ data1 = id; target = tar; data2 = triggered;+ type = 5;+}++void ScriptedEvent::RemoveAura(uint32 id)+{+ data1 = id;+ type = 6;+}++void ScriptedEvent::Equip(uint32 model, uint32 data, uint32 slot, uint32 id)+{+ if(id > 2)+ return;++ data1 = model; data2 = data; data3 = slot;+ x = id; //So I don't use an extra variable+ type = 7;+}++void ScriptedEvent::Fight(Unit *who, bool fight_back)+{+ target = who;+ data1 = fight_back;++ type = 8;+}++void ScriptedEvent::ExitCombat()+{+ type = 9;+}++void ScriptedEvent::SetObjectState(Object *which, uint32 state, bool return_on_expire)+{+ if(!which || which->GetTypeId() != TYPEID_GAMEOBJECT)+ return;++ target = which; data1 = state; data2 = return_on_expire;+ type = 10;+}++void ScriptedEvent::AllowMovement(bool allow)+{+ data1 = allow;+ type = 11;+}++void ScriptedEvent::SetFlag(uint32 index, uint32 flag, bool set)+{+ data1 = index;+ data2 = flag;+ data3 = set;+ type = 12;+}++void ScriptedEvent::ChangeFaction(uint32 faction)+{+ data1 = faction;+ type = 13;+}++void ScriptedEvent::QuestComplete(uint32 quest_id, Player *Target)+{+ target = Target;+ data1 = quest_id;+ type = 14;+}++void ScriptedEvent::Ambush(uint32 ambusher_id, uint32 ambusher_count, uint32 spawn_radius, float X, float Y, float Z)+{+ data1 = ambusher_id;+ data2 = ambusher_count;+ data3 = spawn_radius;++ x = X;y = Y;z = Z;++ type = 15;+}++void ScriptedEvent::Execute()+{+ started = true;+ switch(type)+ {+ case 1:+ switch(data3)+ {+ case 1:+ user->Say(text_data, data1, NULL);+ break;+ case 2:+ user->Yell(text_data, data1, NULL);+ break;+ case 3:+ user->Whisper(target->GetGUID(), text_data);+ break;+ }+ if(data1)+ {+ WorldPacket data(4);+ data.SetOpcode(SMSG_PLAY_SOUND);+ data << uint32(data1);+ user->SendMessageToSet(&data,false);+ }++ break;+ case 2:+ if(!duration)+ {+ float speed = user->GetSpeed(data1 ? MOVE_RUN : MOVE_WALK); + if(speed <= 0)+ speed = 2.5f;++ duration = (uint32)(sqrt(user->GetDistanceSq(x,y,z))/speed * 1000);+ }++ user->SendMonsterMove(x, y, z, 0, data1, duration);+ + break;+ case 3:+ if(data2)+ user->SetUInt32Value(UNIT_NPC_EMOTESTATE,data1);+ else+ user->HandleEmoteCommand(data1);+ break;+ case 4:+ {+ Creature *summon = user->SummonCreature(data1, x, y, z, o, (TempSummonType)data2, data3);++ break;+ }+ case 5:+ user->CastSpell((Unit*)target, data1, data2);+ + break;+ case 6:+ ((Unit*)user)->RemoveAurasDueToSpell(data1);+ break;+ case 7:+ {+ user->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + (int)x, data1);+ user->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (int)2*x, data2);+ user->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (int)2*x + 1, data3);++ break;+ }+ case 8:+ user->AI()->AttackStart((Unit*)target);+ if(data2 && target->GetTypeId() == TYPEID_UNIT)+ ((Creature*)target)->AI()->AttackStart(user);+ + break;+ case 9:+ user->CombatStop(true);+ user->AI()->EnterEvadeMode();+ + break;+ case 10:+ if(data2)+ data3 = ((GameObject*)target)->GetUInt32Value(GAMEOBJECT_STATE);+ ((GameObject*)target)->SetUInt32Value(GAMEOBJECT_STATE, data1);+ break;+ case 11:+ if(data1)+ {+ if(user->getVictim())+ {+ user->GetMotionMaster()->Clear(false);+ user->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*user->getVictim()));+ }+ }+ else+ {+ user->GetMotionMaster()->Clear(false);+ user->GetMotionMaster()->Idle();+ }+ + break;+ case 12:+ if(data3)+ user->SetFlag(data1, data2);+ else+ user->RemoveFlag(data1, data2);+ + break;+ case 13:+ user->setFaction(data1);+ break;+ case 14:+ ((Player*)target)->CompleteQuest(data1);+ break;+ case 15:+ {+ for(int i = 0;i < data2; i++)+ {+ float spwX,spwY,spwZ;+ user->GetRandomPoint(x,y,z,data3,spwX,spwY,spwZ);+ Creature *ambusher = user->SummonCreature(data1, spwX, spwY, spwZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000);+ ambusher->AI()->AttackStart(user);+ guid_data.push_back(ambusher->GetGUID());+ }+ break;+ }+ }+}++void ScriptedEvent::Expire()+{+ switch(type)+ {+ case 2:+ user->Relocate(x,y,z);+ if(o)+ user->SetOrientation(o);++ break;+ case 3:+ if(data2)+ user->SetUInt32Value(UNIT_NPC_EMOTESTATE,0);++ break;+ case 10:+ if(data2)+ ((GameObject*)target)->SetUInt32Value(GAMEOBJECT_STATE, data3);++ break;+ }+}++void ScriptedEvent::Update(const uint32 diff)+{+ duration -= diff;+ switch(type)+ {+ case 15:+ {+ if(guid_data.size())+ {+ for(std::vector<uint64>::iterator itr = guid_data.begin(); itr != guid_data.end(); ++itr)+ {+ Unit *ambusher = Unit::GetUnit(*user, *itr);+ if(!ambusher || ambusher->isDead())+ {+ guid_data.erase(itr);+ break;+ }+ else if(!user->isInCombat() && user->GetDistance(ambusher) < 7)+ user->AI()->AttackStart(ambusher);+ }+ }+ else+ duration = 0;+ }+ }+}++void EventAI::UpdateAI(const uint32 diff)+{+ if(!m_event_list.empty())+ {+ event_list::iterator itr = m_event_list.begin();++ if(!*itr) //Check if something went wrong and prevent crash+ {+ m_event_list.erase(itr);+ return;+ }++ ScriptedEvent *evnt = *itr;++ if(!evnt->started)+ {+ OnEvent(evnt->id);+ evnt->Execute();+ }+ else if(evnt->duration <= diff)+ {+ evnt->Expire();+ OnEventExpire(evnt->id);+ m_event_list.erase(itr);+ delete evnt;+ } + else + evnt->Update(diff);+++ if(evnt->stop_ai)+ return;+ }++ UpdateAI_secondary(diff);+ + ScriptedAI::UpdateAI(diff);++}++ScriptedEvent* EventAI::NewEvent(uint32 id, uint32 duration, Creature *user, bool StopAIactions)+{+ ScriptedEvent *evnt = new ScriptedEvent(id, duration, user, StopAIactions);+ m_event_list.push_back(evnt);+ return evnt;+}++void EventAI::ClearEvents(bool expire_current)+{+ if(!m_event_list.size())+ return;++ event_list::iterator itr = m_event_list.begin();+ + if(*itr && expire_current)+ (*itr)->Expire();++ for( ; itr != m_event_list.end(); ++itr)+ delete *itr;++ m_event_list.clear();+}++ScriptedEvent* EventAI::GetCurrentEvent()+{+ if(m_event_list.size())+ return *m_event_list.begin();+ return NULL;+}\ No newline at end of fileIndex: scripts/creature/EventAI.h===================================================================--- scripts/creature/EventAI.h (revision 0)+++ scripts/creature/EventAI.h (revision 0)@@ -0,0 +1,99 @@+/* Copyright (C) 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>+* This program is free software; you can redistribute it and/or modify+* it under the terms of the GNU General Public License as published by+* the Free Software Foundation; either version 2 of the License, or+* (at your option) any later version.+*+* This program is distributed in the hope that it will be useful,+* but WITHOUT ANY WARRANTY; without even the implied warranty of+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+* GNU General Public License for more details.+*+* You should have received a copy of the GNU General Public License+* along with this program; if not, write to the Free Software+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+*/++#ifndef SCRIPTED_EVENTS_H+#define SCRIPTED_EVENTS_H++#include "../../ScriptMgr.h"++class ScriptedEvent+{+ private:+ //1 - talk, 2 - walk, 3 - emote, 4 - summon, 5 - cast, 6 - remove aura,+ //7 - wield weapon, 8 - fight with , 9 - leave combat, + // 10 - set object state (a.k.a. open/close doors)+ // 11 - allow/disallow movement, 12 - set/remove flag+ // 13 - change faction, 14 - Complete Quest for someone+ // 15 - ambush by mobs+ uint8 type;+ Creature *user;+ Object *target;+ char *text_data;+ uint32 data1,data2,data3;+ float x,y,z,o;+ public:+ ScriptedEvent(uint32 ID,uint32 dur, Creature *initiator, bool stopAI = true, bool continueEvents = false) : + id(ID), duration(dur), user(initiator), target(NULL), type(0), data1(0), + data2(0), data3(0), x(0), y(0), z(0), o(o), text_data(NULL), + started(false), stop_ai(stopAI) {}+ ~ScriptedEvent() {};++ //Duration of event in miliseconds, used for other stuff too+ uint32 duration;+ //Does the event prevent Normal AI actions+ bool stop_ai;+ //whether the event is started+ bool started;+ //Id is used when calling OnEventStart/Expire+ uint32 id;+ //GUID data, for events like ambushes+ std::vector<uint64> guid_data;++ uint8 const GetEventType() { return type; }++ void Talk(char *txt, uint32 Type = 1, uint32 snd = 0, uint8 lang = LANG_UNIVERSAL);+ void Waypoint(float X, float Y, float Z, float O, bool run);+ void Emote(uint32 emo, bool State = false);+ void Summon(uint32 id, uint32 type, uint32 despawn, float X, float Y, float Z, float O);+ void Cast(uint32 id, Object *tar, uint32 triggered);+ void RemoveAura(uint32 id);+ void Equip(uint32 model, uint32 data, uint32 slot, uint32 id);+ void Fight(Unit *who, bool fight_back);+ void ExitCombat();+ void SetObjectState(Object *which, uint32 state, bool return_on_expire = false);+ void AllowMovement(bool allow);+ void SetFlag(uint32 index, uint32 flag, bool set);+ void ChangeFaction(uint32 faction);+ void QuestComplete(uint32 quest_id, Player *Target);+ void Ambush(uint32 ambusher_id, uint32 ambusher_count, uint32 spawn_radius, float X, float Y, float Z);++ void Execute() ;+ void Expire() ;+ void Update(const uint32 diff) ;+};++typedef std::vector<ScriptedEvent*> event_list;++class MANGOS_DLL_DECL EventAI : public ScriptedAI+{+ void UpdateAI(const uint32 diff);+ event_list m_event_list;+ +public:++ EventAI(Creature *c) : ScriptedAI(c) { EnterEvadeMode(); } ++ void ClearEvents(bool expire_current = false);+ ScriptedEvent* NewEvent(uint32 id, uint32 duration, Creature *user, bool StopAIactions = true);+ ScriptedEvent* GetCurrentEvent();++ virtual void UpdateAI_secondary(const uint32 diff) {}++ virtual void OnEvent(uint32 event_id) {} + virtual void OnEventExpire(uint32 event_id) {}+};++#endif\ No newline at end of fileIndex: scripts/zone/westfall/npc_daphne_stilwell.cpp===================================================================--- scripts/zone/westfall/npc_daphne_stilwell.cpp (revision 0)+++ scripts/zone/westfall/npc_daphne_stilwell.cpp (revision 0)@@ -0,0 +1,227 @@+/* Copyright (C) 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>+* This program is free software; you can redistribute it and/or modify+* it under the terms of the GNU General Public License as published by+* the Free Software Foundation; either version 2 of the License, or+* (at your option) any later version.+*+* This program is distributed in the hope that it will be useful,+* but WITHOUT ANY WARRANTY; without even the implied warranty of+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+* GNU General Public License for more details.+*+* You should have received a copy of the GNU General Public License+* along with this program; if not, write to the Free Software+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+*/++#include "../../sc_defines.h"+#include "../../creature/EventAI.h"+#include "../../../../../game/Player.h"++struct Waypoint+{+ float x,y,z,o;+};+++//Some waypoint definitions, for easier use after++static Waypoint toHouse[] = +{+ { -11466.443359, 1530.258789, 50.249241, 5.255720 },+ { -11463.185547, 1525.146362, 50.937778, 5.048375 },+ { -11460.483398, 1526.947510, 50.939514, 0.570917 }+};++static Waypoint toBattle[] =+{+ { -11463.185547, 1525.146362, 50.937778, 3.728201 },+ { -11466.443359, 1530.258789, 50.249241, 1.886439 },+ { -11461.179688, 1539.056885, 52.259014, 1.599460 }+};++static Waypoint toOrchad[] =+{+ { -11463.185547, 1525.146362, 50.937778, 3.728201 },+ { -11466.443359, 1530.258789, 50.249241, 1.886439 },+ { -11480.715820, 1551.802002, 49.263508, 1.893513 }+};++//Thug definitions++#define DEFIAS_RAIDER 6180++#define THUG_SPAWN_X -11431+#define THUG_SPAWN_Y 1607+#define THUG_SPAWN_Z 70.746+#define THUG_SPAWN_O 4.164382+#define THUG_SPAWN_R 5 //radius , because they don't all spawn at the same spot++class npc_DaphneStillwell_AI : public EventAI+{+public:++ npc_DaphneStillwell_AI(Creature *c) : EventAI(c), thug_wave(0), InEvent(false) {}++ std::vector<uint64> thugs; //Thugs out there+ uint8 thug_wave; //Current wave of thugs+ bool InEvent; //Is the quest event in progress+ std::vector<uint64> participants; //Vector because multiple people can start the quest simultaneously++ void EnterEvadeMode()+ {+ m_creature->RemoveAllAttackers();+ m_creature->RemoveAllAuras();+ m_creature->DeleteThreatList();+ m_creature->CombatStop();++ if(!InEvent) //Hack because of incorrect positioning functions (plz gief access to Map::CreatureRelocation)+ DoGoHome();+ }++ void AttackStart(Unit *who)+ {+ ScriptedAI::AttackStart(who);+ }++ void MoveInLineOfSight(Unit *who)+ {+ ScriptedAI::MoveInLineOfSight(who);+ }++ void UpdateAI_secondary(const uint32 diff)+ {+ if(InEvent)+ {+ for(std::vector<uint64>::iterator itr = participants.begin(); itr != participants.end(); ++itr)+ {+ Unit *pala = Unit::GetUnit(*m_creature, *itr);+ if(!pala || pala->isDead())+ {+ participants.erase(itr);+ break;+ }+ }+ }+ }++ void EventFinished(bool complete)+ {+ for(std::vector<uint64>::iterator itr = participants.begin();itr != participants.end(); ++itr)+ {+ Unit *paladin = Unit::GetUnit(*m_creature, *itr);+ if(paladin && paladin->GetTypeId() == TYPEID_PLAYER)+ if(complete)+ ((Player*)paladin)->CompleteQuest(1651);+ else+ ((Player*)paladin)->FailQuest(1651);+ }+ participants.clear();+ }++ void JustDied(Unit *killer)+ {+ ClearEvents();+ EventFinished(false);+ }++ void OnEvent(uint32 event_id)+ {+ switch(event_id)+ {+ case 1: //spawn the first raider which would yell and continue adding events+ {+ Creature *yeller = m_creature->SummonCreature(DEFIAS_RAIDER, THUG_SPAWN_X, THUG_SPAWN_Y, THUG_SPAWN_Z, THUG_SPAWN_O, TEMPSUMMON_TIMED_DESPAWN, 3000);+ yeller->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);+ yeller->Yell("Kill her! Take the farm!", LANG_UNIVERSAL, 0);+ yeller->SendMonsterMove(-11412, 1633, 75, 0, true, 2000);++ NewEvent(0, 0, m_creature)->Talk("To the house! Stay close to me no matter what! I have my gun and ammo there!"); //0 duration, there is an emote with a correct duration below+ NewEvent(0, 3000, m_creature)->Emote(1, true); //Emote state talk for 3 seconds+ + //Time to go to the house+ for(int i = 0; i < 3; i++)+ NewEvent(0,0,m_creature)->Waypoint(toHouse[i].x, toHouse[i].y, toHouse[i].z, toHouse[i].o, true); //0 duration means calculate it according to the creature's speed+ + NewEvent(0, 5000, m_creature)->Emote(69, true); //Emote state 69 (use standing)+ NewEvent(0, 0, m_creature)->Equip(0,0,0,0); //I don't know the correct model for the gun+ + //TO BATTLE !!11!!1!1+ for(int i = 0; i < 3; i++)+ NewEvent(0,0,m_creature)->Waypoint(toBattle[i].x, toBattle[i].y, toBattle[i].z, toBattle[i].o, true);+ + NewEvent(0,5000,m_creature)->Talk("You won't ruin my lands, you scum!", 2); //type 2 == yell+ + NewEvent(0,-1,m_creature, false)->Ambush(DEFIAS_RAIDER, 3, 10, THUG_SPAWN_X, THUG_SPAWN_Y, THUG_SPAWN_Z); //Spawn trigger+ NewEvent(0,5000,m_creature)->Talk("One more down!");++ NewEvent(0,-1,m_creature, false)->Ambush(DEFIAS_RAIDER, 4, 10, THUG_SPAWN_X, THUG_SPAWN_Y, THUG_SPAWN_Z); //Spawn trigger+ NewEvent(0,5000,m_creature)->Talk("One more down!");++ NewEvent(0,-1,m_creature, false)->Ambush(DEFIAS_RAIDER, 5, 10, THUG_SPAWN_X, THUG_SPAWN_Y, THUG_SPAWN_Z); //Spawn trigger++ NewEvent(2, 0, m_creature)->Talk("We've done it! We Won!");+ NewEvent(0, 2000, m_creature)->Emote(4);+ NewEvent(0, 0, m_creature)->Talk("Meet me at the orchad--I just need to put my gun away");++ //Move to house .. again+ for(int i = 0; i < 3; i++)+ NewEvent(0,0,m_creature)->Waypoint(toHouse[i].x, toHouse[i].y, toHouse[i].z, toHouse[i].o, true); //0 duration means calculate it according to the creature's speed++ NewEvent(0, 5000, m_creature)->Emote(69); //Work emote here+ NewEvent(0, 0, m_creature)->Equip(0,0,0,0); //Unequip gun++ //Move to orchad+ for(int i = 0; i < 3; i++)+ NewEvent(0,0,m_creature)->Waypoint(toOrchad[i].x, toOrchad[i].y, toOrchad[i].z, toOrchad[i].o, true);+ + NewEvent(0,0,m_creature)->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER, true);+ + break;+ }+ case 2: //Quest Completed+ {+ EventFinished(true);+ }+ }+ }++ void StartEvent(Player *initiator)+ {+ participants.push_back(initiator->GetGUID()); //Remember who started the whole ordeal so we can give him credit later+ thug_wave = 0;++ if(InEvent) // If Someone else started already+ {+ ClearEvents();+ }++ //use '0' IDs for insignificant events+ NewEvent(0, 5000, m_creature); //I.E. just sit there staring at emty space+ NewEvent(1, 5000, m_creature)->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER, false); //remove the questgiver flag+ //The rest of the events are in the OnEvent function+ }+};++bool QuestAccept_npc_DaphneStillwell(Player *player, Creature *_Creature, Quest *_Quest)+{+ if(_Quest->GetQuestId() == 1651)+ ((npc_DaphneStillwell_AI*)_Creature->AI())->StartEvent(player);+ + return true;+}++CreatureAI* GetAI_npc_DaphneStillwell(Creature *c)+{+ return new npc_DaphneStillwell_AI(c);+}++void AddSC_npc_DaphneStillwell()+{+ Script *newscript = new Script;+ newscript->Name = "npc_daphne_stillwell";+ newscript->GetAI = GetAI_npc_DaphneStillwell ;+ newscript->pQuestAccept = &QuestAccept_npc_DaphneStillwell;+ m_scripts[nrscripts++] = newscript;+}+Index: VC80/80ScriptDev2.vcproj===================================================================--- VC80/80ScriptDev2.vcproj (revision 136)+++ VC80/80ScriptDev2.vcproj (working copy)@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="windows-1250"?> <VisualStudioProject ProjectType="Visual C++"- Version="8.00"+ Version="8,00" Name="ScriptDev2" ProjectGUID="{4295C8A9-79B7-4354-8064-F05FB9CA0C96}" RootNamespace="ScriptDev2"@@ -216,6 +216,14 @@ Name="creature" > <File+ RelativePath="..\scripts\creature\EventAI.cpp"+ >+ </File>+ <File+ RelativePath="..\scripts\creature\EventAI.h"+ >+ </File>+ <File RelativePath="..\scripts\creature\mob_defias.cpp" > </File>@@ -1250,6 +1258,10 @@ <Filter Name="Westfall" >+ <File+ RelativePath="..\scripts\zone\westfall\npc_daphne_stilwell.cpp"+ >+ </File> </Filter> <Filter Name="Wetlands"