1) What is the Kronos Project and how was it planned?
2) Did we stick to the plan? What went according to plan and what went wrong?
3) What are some key hints and tips that can be used to create a engaging environment for the players to interact with?
4) Can we see some examples of scripts and how some of the systems work?
5) Conclusion of development so far.
6) Previews.
7) Download link for progress so far.
1) What is the Kronos Project and how was it planned?
Basic Information
The Kronos Project originated as an ordinary server with a dedicated server and a small team. Our aim was to create the ultimate server which has mixed PvE and PvP to a high standard. It featured you starting at level 1, and levelling to level 20 as Alliance or Horde; each containing separate epic, custom worlds. Once you eventually progress through the story line, reaching the end and finished the fight, you can enter PvE instances and raids or PvP in one of several custom battlegrounds. As well as the battlegrounds there is open world phased PvP, so normal players levelling will not get 'ganked' by higher levels. Of course, the PvE has a strict story line and role players will enjoy it as well as the casual player.
Initial Ideas
Attachment 2969
Attachment 2970
2) Did we stick to the plan? What went according to plan and what went wrong?
Partially. Initially we did, we worked from the basic concept ideas we had. Alliance is what we started with, and it was a strong learning curve. At this point, I had a strong team, and we developed well. I started with the intro system (which you can see in previews) which features a mini intro upon logging in (which Blizzard now use for Goblin's and Worgan's! I sometimes think they copy my ideas. ) After this system was worked out, I designed the camp.
The initial starting zone is a very important part of a server, especially for one where you want balanced RPPvP. Since I used Morgan's Vigal I already had a destroyed tower and a small barricade and gateway. I started by showing it was controlled by the Alliance with a Alliance banner. A note here is to change the object type to 5 so that it actives as a passive object in the world. That was the only gameobject I used, you don't need excessive gameobjects all over the place, work with what Blizzard gives you. I placed class trainers around the encampment in a logical sense, and gave some timed emotes to make it more realistic as well as equipping weapons. From there, I spawned the people to make up the numbers - Guards. I had Horde npc's randomly spawn and attack the base with some explosion visuals to add to the realism of the enviroment. I then added the quest npc's and added a quest template. The reason I only added a quest template is because we can come to fine tune and add in RP text and such later on, this is not that important when we may need to change it later on.
In this fashion, I worked through Alliance, learning an increadable amount as I went along. Dynashock created a racing system (see previews) which allowed you to race againts various creatures while events happened around you (caves collapsing and the likes). This system allowed to unlock mounts. That's right, you had to unlock mounts. Don't give things away for free, add original content that allows you to unlock essential things that people will want to work for. Don't make them have to do it, make it as a challenge they can do. Also make sure quests are never just kill npc's, always add a variety to keep your audience captured.
After I had completed Alliance 1-15 I worked on Horde, which is far better. This is because I learnt as I went along. By this time I was the last developer, and I had to work on this alone which took months; but the quality of work shown is incredible.
What went wrong? Lots of things. Developers slowly left or become inactive, and people had real life issues. Our dedicated server disapeared and drama was left right and centre. This is why I took the project to localhost where I can work on it, as a repack or a server (undecided - will decide once finished). In terms of in game development, there was a huge issue. Searing Gorge and Burning Stepps are too small! I don't know how I planned to fit 20 levels into here, I certainly didn't consider the scale of the matter. Luckily I added solutions, for example with Horde at level 15 you receive a key that allows you to access Stonewrought Pass. From here you can pass into Loch Modan, where I have sealed off many areas by cleverly using the mountain system. There is a solution to every problem you may encounter, you just have to work with it and find it.
3) What are some key hints and tips that can be used to create a engaging environment for the players to interact with?
Be simple. Add subtle humour. Make everything interactive.
You have to get the player involved, you have to get them to believe that this is a real scenario and that they can make a difference; imagine yourself in their shoes. Spawn gameobjects in a realistic fashion, look at how blizzard do it. DO NOT spawn thousands of gameobjects, since this looks unprofessional and will cause lag depending on your client. Add emotions to various creatures (.mod npc emoteid) for example if I want a creature to be dancing I would do .mod npc 10. Creature emotion id's 400 to 410 are 'special emotes'. Lots of models have special emotes, which have some epic effects, and you should use these to your advantage. An example is 400 on a human will cause them to ballroom dance like in Karazhan, and on a Vrykul they have loads.
Bytes are a really useful way of making your server look proffesional, DO NOT use them on players, and this is a list of what happens when you use them on creatures:
.mod bytes0 X = Unknown effect.
.mod bytes1 1 = Makes the npc sit down.
.mod bytes1 2 = something.
.mod bytes1 3 = Sleeping emotion.
.mod bytes1 4 = Sitting down in chair.
.mod bytes1 5 = Sitting down in chair.
.mod bytes1 6 = Sitting down in chair.
.mod bytes1 7 = Dead emotion.
.mod bytes1 8 = Kneel emotion.
.mod bytes2 1 = Makes left and right handed weapons appear to be out instead of sheathed.
.mod bytes2 2 = Makes any bow/gun be in their hand instead of sheathed.
.mod bytes3 X = Unknown effect, affects things such as swimming/flying.
Many bytes can be reset if they enter combat - restart server after changing the bytes, then fight the creature. If he resets, you will have to set the bytes again and then .mod flags 2 so that he can't enter combat.
Flags are also a very useful way to make your server have that proffesional effect.
.mod flags -10 = Makes the npc untargetable (unless your a GM go near him and use .npc select).
.mod flags 2 = Makes the target unattackable, it will never enter combat, even if his faction is 21.
.mod flags 10 = Makes the creature look like a player!
There are hundreds of flags, and they can change if there is a major patch.
Also don't be afraid to spam waypoints. Although they look rubbish with them all moving at once and all moving after 5 seconds, after a server restart it will look much better. Spread them out also, and make certain npc's have long paths that they walk without stopping (.way show - .way waittime 0). Although it says having waypoints at less than 5 seconds will cause lag, it won't unless you have ~20 or more creatures in the same small area at 0 second waypoints.
It's amazing what you can do with Lua and ai_agents. Use your imagination, you have a wyrm (dragonking). What do dragons do? We go into ai_agents and add make the creature cast fireball every few seconds (see arcemu wiki on how ai_agents work). Simple things like this have a huge impact. Also take a look at npc_text, instead of when talking to creatures having "Hey there $N, how can I help you?" or whatever it is, change it to something interesting for each creature. If I have a quest where you are to learn the ancient ways of Hap Ki Do, then I would say something like "Your the best they could send? You pathetic excuse of a $C, let me show you the true $C!".
Note; in text, $C displays the players class and $N displays the players name.
4) Can we see some examples of scripts and how some of the systems work?
Here is my intro system you can study, I believe it shows how cleverly you can use simple Lua to have some awesome effects.
local PlayerA local NPC_SPAWNER_A local NPC_SPAWNER_B local PlayerB local NPC_A local NPC_B local Count = 0 function NPCGIA_GJOEAOJG_HXOJ(pUnit, Event) NPC_SPAWNER_A = pUnit end RegisterUnitEvent(99955, 18, "NPCGIA_GJOEAOJG_HXOJ") function NPCGIA_GJOEAOJG_HXOJ_Z(pUnit, Event) NPC_SPAWNER_B = pUnit end RegisterUnitEvent(99954, 18, "NPCGIA_GJOEAOJG_HXOJ_Z") function GHOUL_SPAWNED_CARION(pUnit, Event) NPC_A = pUnit end RegisterUnitEvent(26515, 18, "GHOUL_SPAWNED_CARION") function NECROMANCER_MASTER_SPAWN(pUnit, Event) NPC_B = pUnit end RegisterUnitEvent(232771, 18, "NECROMANCER_MASTER_SPAWN") function zzz_OnFirstEnterWorld(event, pPlayer) local race = pPlayer:GetPlayerRace() -- We get the race of the person that we shall use if race == 1 or race == 3 or race == 4 or race == 7 or race == 11 then -- THIS IS THE ALLIANCE RACES, change to what you want. if PlayerA == nil then pPlayer:CastSpell(50010) -- Visual pPlayer:CastSpell(53658) -- Visual pPlayer:SetPlayerLock(1) -- Stop him moving pPlayer:MovePlayerTo(pPlayer:GetX(),pPlayer:GetY(),pPlayer:GetZ()+0.1, pPlayer:GetO(), 12288) -- Move him slightly to play client side effects and shizzle pPlayer:CastSpell(50010) -- More visuals pPlayer:CastSpell(28330) -- More visuals pPlayer:CastSpell(53658) -- More visuals PlayerA = pPlayer -- Here we tell the script we are now using a player RegisterTimedEvent("TesttestTesttestTest_zzogje", 4000, 1) -- players cant register events so we use a world event RegisterTimedEvent("TesttestTesttestTest_zzogje_z", 500, 2) -- See above end else if PlayerB == nil then -- Horde pPlayer:SetPlayerLock(1) pPlayer:CastSpell(46940) -- Bleed pPlayer:SetStandState(7) PlayerB = pPlayer RegisterTimedEvent("GHOUL_PLAY_EMOTE", 1000, 1) RegisterTimedEvent("GHOUL_PLAY_EMOTE_STOP", 5000, 1) end end end function GHOUL_PLAY_EMOTE(pUnit, Event) NPC_A:Emote(398, 10000) PlayerB:SetStandState(7) NPC_B:SetNPCFlags(1) --PlayerB:CastSpell(57626) -- Feign Death end function GHOUL_PLAY_EMOTE_STOP(pUnit, Event) NPC_B:SendChatMessage(12,0,"What have you found ghoul?") NPC_B:MoveTo(-6431, -2047, 260.5, 2.605783) NPC_B:RegisterEvent("Hangon_A_Moment_nubcake", 4700, 1) end function Hangon_A_Moment_nubcake(pUnit, Event) NPC_B:SendChatMessage(12,0,"Ah.. I should be able to save this creature.") NPC_B:Emote(1, 4000) NPC_B:RegisterEvent("Hangon_A_Moment_nubcake_z", 4500, 1) end function Hangon_A_Moment_nubcake_z(pUnit, Event) NPC_B:ChannelSpell(57797, PlayerB) NPC_B:RegisterEvent("Hangon_A_Moment_nubcake_zz", 6000, 1) end function Hangon_A_Moment_nubcake_zz(pUnit, Event) NPC_B:StopChannel() PlayerB:SetStandState(0) NPC_B:SendChatMessage(12,0,"Your fine. Get up, you look pathetic... Come on, try and move!") --PlayerB:SendBroadcastMessage("Hint: Try to move left or right to stand up.") --PlayerB:SendAreaTriggerMessage("Hint: Try to move left or right to stand up.") PlayerB:SetPlayerLock(0) PlayerB:RemoveAura(46940) -- Bleed PlayerB:CastSpell(61126) NPC_B:RegisterEvent("Hangon_A_Moment_nubcake_zzz", 3000, 1) end function Hangon_A_Moment_nubcake_zzz(pUnit, Event) PlayerB = nil NPC_B:SetNPCFlags(2) NPC_B:ReturnToSpawnPoint() end -- Below is alliance shit function TesttestTesttestTest_zzogje_z(pUnit, Event) PlayerA:CastSpell(53658) -- Some random visual because moving them is buggy and disables it end function TesttestTesttestTest_zzogje(pUnit, Event) --[[if NPC_SPAWNER_A == nil then -- if 1 is nil NPC_SPAWNER_A = PlayerA:GetCreatureNearestCoords(-8399, -2772.4, 194.8, 99955) if NPC_SPAWNER_A == nil then -- still nil reset PlayerA:RemoveAura(53658) playerA:RemoveAura(28330) PlayerA = nil else -- otherwise we have value if NPC_SPAWNER_B == nil then -- if 2 is nil PlayerA:GetCreatureNearestCoords(-8402, -2765.85, 195, 99954) if NPC_SPAWNER_B == nil then -- still nil PlayerA:RemoveAura(53658) playerA:RemoveAura(28330) PlayerA = nil else -- otherwise NPC_SPAWNER_A:SendChatMessage(12,0,"We got another live one!") -- ok, our first npc is doing something NPC_SPAWNER_A:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_B:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_A:RegisterEvent("SayHelloToMyLittleFriend_Z_z_Z", 5000, 1) -- now we can use the npc to control the event rather than the idiotic world event end else NPC_SPAWNER_A:SendChatMessage(12,0,"We got another live one!") -- ok, our first npc is doing something NPC_SPAWNER_A:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_B:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_A:RegisterEvent("SayHelloToMyLittleFriend_Z_z_Z", 5000, 1) -- now we can use the npc to control the event rather than the idiotic world event end end else if NPC_SPAWNER_B == nil then -- if 2 is nil PlayerA:GetCreatureNearestCoords(-8402, -2765.85, 195, 99954) if NPC_SPAWNER_B == nil then -- still nil PlayerA:RemoveAura(53658) playerA:RemoveAura(28330) PlayerA = nil else -- otherwise NPC_SPAWNER_A:SendChatMessage(12,0,"We got another live one!") -- ok, our first npc is doing something NPC_SPAWNER_A:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_B:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_A:RegisterEvent("SayHelloToMyLittleFriend_Z_z_Z", 5000, 1) -- now we can use the npc to control the event rather than the idiotic world event end else ]] -- All of the above code was me trying to debug what I found out to be Tikki's idiotic copy + paste on spawn functions >_< RRAGGEEEEE NPC_SPAWNER_A:SendChatMessage(12,0,"We got another live one!") -- ok, our first npc is doing something NPC_SPAWNER_A:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_B:ChannelSpell(51361, PlayerA) -- Visual NPC_SPAWNER_A:RegisterEvent("SayHelloToMyLittleFriend_Z_z_Z", 5000, 1) -- now we can use the npc to control the event rather than the idiotic world event --end --end end RegisterServerHook(3, "zzz_OnFirstEnterWorld") -- Register the on first enter world function SayHelloToMyLittleFriend_Z_z_Z(pUnit, Event) local Name = PlayerA:GetName() -- Get his name NPC_SPAWNER_B:SendChatMessage(12, 0, "Woah, are you alright "..Name.."? Your lucky to be alive! Let us give you a hand.") -- Send a message including his name NPC_SPAWNER_A:RegisterEvent("CastReviveVisualThingyTeheTeheTehe", 4000, 1) -- next event end function CastReviveVisualThingyTeheTeheTehe(pUnit, Event) NPC_SPAWNER_A:StopChannel() -- stop it NPC_SPAWNER_B:StopChannel() -- stop it NPC_SPAWNER_B:FullCastSpellOnTarget(37755, PlayerA) -- ress visual NPC_SPAWNER_A:FullCastSpellOnTarget(37755, PlayerA) -- ress visual NPC_SPAWNER_A:RegisterEvent("LetPlayerMoveaogyaohea", 2400, 1) -- reset player end function LetPlayerMoveaogyaohea(pUnit, Event) PlayerA:SetPlayerLock(0) -- let the player move PlayerA:CastSpell(21074) -- ress visual PlayerA:RemoveAura(50010) -- delete visual PlayerA:RemoveAura(28330) -- delete visual PlayerA:RemoveAura(53658) -- delete visual NPC_SPAWNER_A:SendChatMessage(12, 0, "There we go! You should report to Commander Howser.") -- ohai a message NPC_SPAWNER_A:RegisterEvent("MassDespawnAndResetoajphae", 1000, 1) -- reset event end function MassDespawnAndResetoajphae(pUnit, Event) PlayerA = nil -- All we need to do is say that the slot for a creating character is nil again end
As far as Kronos is concerned, it is taking me much longer than I expected. I started this project in october 2009, and it is now May 2010 and so far I've completed:
Alliance 1-15
Horde 1-18
4 Races
1 Custom instance
1 instance design and template
Lots of systems such as anti-ganking.
PvE takes forever to complete if your going custom to a high quality. THINK before you start up a project as large as I have.
6) Previews:
(I apologise now for the awful quality of sound - you may want to mute it)
YouTube - Alliance Custom Leveling Preview
YouTube - Horde Leveling 1-5 (Custom Content)
YouTube - A Race againts a NPC Quest
http://www.youtube.com/watch?v=gNlYl_E10Mg
7) Download link for progress so far:
I am providing these for you to test, on the assumption that you will provide feedback and bug reports. This is currently NOT a learning resource, since all scripts are encrypted. The final product will be open source.
username: repack
password: repack
Version 2.1
Please note, only patch 3.3.3 is currently supported in this version.
Password to emulator currently is: stoneharry
Rapidshare: (Coming Soon)
Mediafire: http://www.mediafire.com/?wumyykwiztt
Filebeam: http://filebeam.com/a63382f29fc288bc0df6a545ac057c60
~Harry.
vBulletin Message