Index: 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
//Zangramarsh
Index: 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
+* 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(*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::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 file
Index: 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
+* 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 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 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 file
Index: 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
+* 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 thugs; //Thugs out there
+ uint8 thug_wave; //Current wave of thugs
+ bool InEvent; //Is the quest event in progress
+ std::vector 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::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::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 @@
+
+
+
+
@@ -1250,6 +1258,10 @@
+
+