فهرست منبع

- Quests: Newbie rewards implementation. Requires core update [L1716], since now characters' newbie field will work as INT instead of boolean. There are more quests that would make use of this facility, btw.
- Characters field optimization, part I: changing field types to those available in MySQL. This should improve performance and doesn't require changes in 3rd party tools. Upcoming field name changes are being prepared, tho. (For these SQL changes is that we added backup facilities in the scripts ;))
- Creating new 'maintenance' section under the SQL folder, read documentation.txt for further details.

DrLecter 17 سال پیش
والد
کامیت
77fa3cfb5f

+ 55 - 41
datapack_development/data/scripts/quests/101_SwordOfSolidarity/__init__.py

@@ -7,19 +7,26 @@ from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
 
 qn = "101_SwordOfSolidarity"
 
-ROIENS_LETTER_ID = 796
-HOWTOGO_RUINS_ID = 937
-BROKEN_SWORD_HANDLE_ID = 739
-BROKEN_BLADE_BOTTOM_ID = 740
-BROKEN_BLADE_TOP_ID = 741
-ALLTRANS_NOTE_ID = 742
-SWORD_OF_SOLIDARITY_ID = 738
+ROIENS_LETTER = 796
+HOWTOGO_RUINS = 937
+BROKEN_SWORD_HANDLE = 739
+BROKEN_BLADE_BOTTOM = 740
+BROKEN_BLADE_TOP = 741
+ALLTRANS_NOTE = 742
+SWORD_OF_SOLIDARITY = 738
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 8
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
  def __init__(self,id,name,descr):
      JQuest.__init__(self,id,name,descr)
-     self.questItemIds = [ALLTRANS_NOTE_ID, HOWTOGO_RUINS_ID, BROKEN_BLADE_TOP_ID, BROKEN_BLADE_BOTTOM_ID, ROIENS_LETTER_ID, BROKEN_SWORD_HANDLE_ID]
+     self.questItemIds = [ALLTRANS_NOTE, HOWTOGO_RUINS, BROKEN_BLADE_TOP, BROKEN_BLADE_BOTTOM, ROIENS_LETTER, BROKEN_SWORD_HANDLE]
 
  def onEvent (self,event,st) :
     htmltext = event
@@ -27,18 +34,25 @@ class Quest (JQuest) :
         st.set("cond","1")
         st.setState(State.STARTED)
         st.playSound("ItemSound.quest_accept")
-        st.giveItems(ROIENS_LETTER_ID,1)
+        st.giveItems(ROIENS_LETTER,1)
     elif event == "30283-02.htm" :
         st.set("cond","2")
-        st.takeItems(ROIENS_LETTER_ID,st.getQuestItemsCount(ROIENS_LETTER_ID))
-        st.giveItems(HOWTOGO_RUINS_ID,1)
+        st.takeItems(ROIENS_LETTER,st.getQuestItemsCount(ROIENS_LETTER))
+        st.giveItems(HOWTOGO_RUINS,1)
     elif event == "30283-07.htm" :
-        st.takeItems(BROKEN_SWORD_HANDLE_ID,-1)
-        st.giveItems(SWORD_OF_SOLIDARITY_ID,1)
+        st.takeItems(BROKEN_SWORD_HANDLE,-1)
+        st.giveItems(SWORD_OF_SOLIDARITY,1)
         st.set("cond","0")
         st.exitQuest(False)
         st.playSound("ItemSound.quest_finish")
-        st.set("onlyone","1")        
+        st.set("onlyone","1")
+        # check the player state against this quest newbie rewarding mark.
+        newbie = player.getNewbie()
+        if newbie | NEWBIE_REWARD != newbie :
+           player.setNewbie(newbie|NEWBIE_REWARD)
+           if not player.getClassId().isMage() :
+              st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,7000)
+              st.playTutorialVoice("tutorial_voice_026")
     return htmltext
 
 
@@ -63,39 +77,39 @@ class Quest (JQuest) :
    elif npcId == 30008 and st.getInt("cond")==0 and st.getInt("onlyone")==1 :
         htmltext = "<html><body>This quest has already been completed.</body></html>"
    if id == State.STARTED: 
-       if npcId == 30008 and st.getInt("cond")==1 and (st.getQuestItemsCount(ROIENS_LETTER_ID)==1) :
+       if npcId == 30008 and st.getInt("cond")==1 and (st.getQuestItemsCount(ROIENS_LETTER)==1) :
             htmltext = "30008-05.htm"
-       elif npcId == 30008 and st.getInt("cond")>=2 and st.getQuestItemsCount(ROIENS_LETTER_ID)==0 and st.getQuestItemsCount(ALLTRANS_NOTE_ID)==0 :
-            if st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID) :
+       elif npcId == 30008 and st.getInt("cond")>=2 and st.getQuestItemsCount(ROIENS_LETTER)==0 and st.getQuestItemsCount(ALLTRANS_NOTE)==0 :
+            if st.getQuestItemsCount(BROKEN_BLADE_TOP) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM) :
               htmltext = "30008-12.htm"
-            if (st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID)) <= 1 :
+            if (st.getQuestItemsCount(BROKEN_BLADE_TOP) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM)) <= 1 :
               htmltext = "30008-11.htm"
-            if st.getQuestItemsCount(BROKEN_SWORD_HANDLE_ID) > 0 :
+            if st.getQuestItemsCount(BROKEN_SWORD_HANDLE) > 0 :
               htmltext = "30008-07.htm"
-            if st.getQuestItemsCount(HOWTOGO_RUINS_ID) == 1 :
+            if st.getQuestItemsCount(HOWTOGO_RUINS) == 1 :
               htmltext = "30008-10.htm"
-       elif npcId == 30008 and st.getInt("cond")==4 and st.getQuestItemsCount(ROIENS_LETTER_ID)==0 and st.getQuestItemsCount(ALLTRANS_NOTE_ID) :
+       elif npcId == 30008 and st.getInt("cond")==4 and st.getQuestItemsCount(ROIENS_LETTER)==0 and st.getQuestItemsCount(ALLTRANS_NOTE) :
             htmltext = "30008-06.htm"
             st.set("cond","5")
-            st.takeItems(ALLTRANS_NOTE_ID,st.getQuestItemsCount(ALLTRANS_NOTE_ID))
-            st.giveItems(BROKEN_SWORD_HANDLE_ID,1)
-       elif npcId == 30283 and st.getInt("cond")==1 and st.getQuestItemsCount(ROIENS_LETTER_ID)>0 :
+            st.takeItems(ALLTRANS_NOTE,st.getQuestItemsCount(ALLTRANS_NOTE))
+            st.giveItems(BROKEN_SWORD_HANDLE,1)
+       elif npcId == 30283 and st.getInt("cond")==1 and st.getQuestItemsCount(ROIENS_LETTER)>0 :
             htmltext = "30283-01.htm"
-       elif npcId == 30283 and st.getInt("cond")>=2 and st.getQuestItemsCount(ROIENS_LETTER_ID)==0 and st.getQuestItemsCount(HOWTOGO_RUINS_ID)>0 :
-            if (st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID)) == 1 :
+       elif npcId == 30283 and st.getInt("cond")>=2 and st.getQuestItemsCount(ROIENS_LETTER)==0 and st.getQuestItemsCount(HOWTOGO_RUINS)>0 :
+            if (st.getQuestItemsCount(BROKEN_BLADE_TOP) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM)) == 1 :
               htmltext = "30283-08.htm"
-            if (st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID)) == 0 :
+            if (st.getQuestItemsCount(BROKEN_BLADE_TOP) + st.getQuestItemsCount(BROKEN_BLADE_BOTTOM)) == 0 :
               htmltext = "30283-03.htm"
-            if st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID) :
+            if st.getQuestItemsCount(BROKEN_BLADE_TOP) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM) :
               htmltext = "30283-04.htm"
               st.set("cond","4")
-              st.takeItems(HOWTOGO_RUINS_ID,st.getQuestItemsCount(HOWTOGO_RUINS_ID))
-              st.takeItems(BROKEN_BLADE_TOP_ID,st.getQuestItemsCount(BROKEN_BLADE_TOP_ID))
-              st.takeItems(BROKEN_BLADE_BOTTOM_ID,st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID))
-              st.giveItems(ALLTRANS_NOTE_ID,1)
-       elif npcId == 30283 and st.getInt("cond")==4 and st.getQuestItemsCount(ALLTRANS_NOTE_ID) :
+              st.takeItems(HOWTOGO_RUINS,st.getQuestItemsCount(HOWTOGO_RUINS))
+              st.takeItems(BROKEN_BLADE_TOP,st.getQuestItemsCount(BROKEN_BLADE_TOP))
+              st.takeItems(BROKEN_BLADE_BOTTOM,st.getQuestItemsCount(BROKEN_BLADE_BOTTOM))
+              st.giveItems(ALLTRANS_NOTE,1)
+       elif npcId == 30283 and st.getInt("cond")==4 and st.getQuestItemsCount(ALLTRANS_NOTE) :
             htmltext = "30283-05.htm"
-       elif npcId == 30283 and st.getInt("cond")==5 and st.getQuestItemsCount(BROKEN_SWORD_HANDLE_ID) :
+       elif npcId == 30283 and st.getInt("cond")==5 and st.getQuestItemsCount(BROKEN_SWORD_HANDLE) :
             htmltext = "30283-06.htm"
    return htmltext
 
@@ -105,16 +119,16 @@ class Quest (JQuest) :
    if st.getState() == State.STARTED :
        npcId = npc.getNpcId()
        if npcId in [20361,20362] :
-          if st.getQuestItemsCount(HOWTOGO_RUINS_ID) :
-             if st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) == 0 :
+          if st.getQuestItemsCount(HOWTOGO_RUINS) :
+             if st.getQuestItemsCount(BROKEN_BLADE_TOP) == 0 :
                 if st.getRandom(5) == 0 :
-                   st.giveItems(BROKEN_BLADE_TOP_ID,1)
+                   st.giveItems(BROKEN_BLADE_TOP,1)
                    st.playSound("ItemSound.quest_middle")
-             elif st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID) == 0 :
+             elif st.getQuestItemsCount(BROKEN_BLADE_BOTTOM) == 0 :
                 if st.getRandom(5) == 0 :
-                   st.giveItems(BROKEN_BLADE_BOTTOM_ID,1)
+                   st.giveItems(BROKEN_BLADE_BOTTOM,1)
                    st.playSound("ItemSound.quest_middle")
-          if st.getQuestItemsCount(BROKEN_BLADE_TOP_ID) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM_ID) :
+          if st.getQuestItemsCount(BROKEN_BLADE_TOP) and st.getQuestItemsCount(BROKEN_BLADE_BOTTOM) :
              st.set("cond","3")
    return
 
@@ -127,4 +141,4 @@ QUEST.addTalkId(30008)
 QUEST.addTalkId(30283)
 
 QUEST.addKillId(20361)
-QUEST.addKillId(20362)
+QUEST.addKillId(20362)

+ 14 - 1
datapack_development/data/scripts/quests/103_SpiritOfCraftsman/__init__.py

@@ -17,6 +17,12 @@ PRESERVE_OIL_ID = 972
 ZOMBIE_HEAD_ID = 973
 STEELBENDERS_HEAD_ID = 974
 BLOODSABER_ID = 975
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 8
 
 class Quest (JQuest) :
 
@@ -101,6 +107,13 @@ class Quest (JQuest) :
             st.exitQuest(False)
             st.playSound("ItemSound.quest_finish")
             st.set("onlyone","1")
+            # check the player state against this quest newbie rewarding mark.
+            newbie = player.getNewbie()
+            if newbie | NEWBIE_REWARD != newbie :
+               player.setNewbie(newbie|NEWBIE_REWARD)
+               if not player.getClassId().isMage() :
+                  st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,7000)
+                  st.playTutorialVoice("tutorial_voice_026")
    return htmltext
 
  def onKill(self,npc,player,isPet):
@@ -145,4 +158,4 @@ QUEST.addKillId(20015)
 QUEST.addKillId(20020)
 QUEST.addKillId(20455)
 QUEST.addKillId(20517)
-QUEST.addKillId(20518)
+QUEST.addKillId(20518)

+ 35 - 24
datapack_development/data/scripts/quests/104_SpiritOfMirrors/__init__.py

@@ -7,20 +7,25 @@ from net.sf.l2j import Config
 
 qn = "104_SpiritOfMirrors" 
 
-GALLINS_OAK_WAND_ID = 748 
-WAND_SPIRITBOUND1_ID = 1135 
-WAND_SPIRITBOUND2_ID = 1136 
-WAND_SPIRITBOUND3_ID = 1137 
-WAND_OF_ADEPT_ID = 747 
-SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5790 
+GALLINS_OAK_WAND = 748 
+WAND_SPIRITBOUND1 = 1135 
+WAND_SPIRITBOUND2 = 1136 
+WAND_SPIRITBOUND3 = 1137 
+WAND_OF_ADEPT = 747
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 2
+SPIRITSHOT_NO_GRADE_FOR_BEGINNERS = 5790 
 SPIRITSHOT_NO_GRADE = 2509 
-SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5789
 SOULSHOT_NO_GRADE = 1835
 
 DROPLIST = { 
-27003: (WAND_SPIRITBOUND1_ID), 
-27004: (WAND_SPIRITBOUND2_ID), 
-27005: (WAND_SPIRITBOUND3_ID) 
+27003: (WAND_SPIRITBOUND1), 
+27004: (WAND_SPIRITBOUND2), 
+27005: (WAND_SPIRITBOUND3) 
 } 
 
 # Helper function - If player have all quest items returns 1, otherwise 0 
@@ -35,7 +40,7 @@ class Quest (JQuest) :
 
  def __init__(self,id,name,descr):
    JQuest.__init__(self,id,name,descr)
-   self.questItemIds = [GALLINS_OAK_WAND_ID, WAND_SPIRITBOUND1_ID, WAND_SPIRITBOUND2_ID, WAND_SPIRITBOUND3_ID]
+   self.questItemIds = [GALLINS_OAK_WAND, WAND_SPIRITBOUND1, WAND_SPIRITBOUND2, WAND_SPIRITBOUND3]
 
  def onEvent (self,event,st) : 
     htmltext = event 
@@ -43,9 +48,9 @@ class Quest (JQuest) :
       st.set("cond","1") 
       st.setState(State.STARTED)
       st.playSound("ItemSound.quest_accept") 
-      st.giveItems(GALLINS_OAK_WAND_ID,1) 
-      st.giveItems(GALLINS_OAK_WAND_ID,1) 
-      st.giveItems(GALLINS_OAK_WAND_ID,1) 
+      st.giveItems(GALLINS_OAK_WAND,1) 
+      st.giveItems(GALLINS_OAK_WAND,1) 
+      st.giveItems(GALLINS_OAK_WAND,1) 
     return htmltext 
 
  def onTalk (self,npc,player): 
@@ -59,7 +64,8 @@ class Quest (JQuest) :
      st.set("onlyone","0") 
    if npcId == 30017 and st.getInt("cond")==0 and st.getInt("onlyone")==0 : 
      if player.getRace().ordinal() != 0 : 
-        htmltext = "30017-00.htm" 
+        htmltext = "30017-00.htm"
+        st.exitQuest(1)
      elif player.getLevel() >= 10 : 
         htmltext = "30017-02.htm" 
         return htmltext 
@@ -69,19 +75,24 @@ class Quest (JQuest) :
    elif npcId == 30017 and st.getInt("cond")==0 and st.getInt("onlyone")==1 : 
       htmltext = "<html><body>This quest has already been completed</body></html>" 
    elif id == State.STARTED : 
-     if npcId == 30017 and st.getInt("cond") and st.getQuestItemsCount(GALLINS_OAK_WAND_ID)>=1 and not HaveAllQuestItems(st) : 
+     if npcId == 30017 and st.getInt("cond") and st.getQuestItemsCount(GALLINS_OAK_WAND)>=1 and not HaveAllQuestItems(st) : 
         htmltext = "30017-04.htm" 
      elif npcId == 30017 and st.getInt("cond")==3 and HaveAllQuestItems(st) : 
         for mobId in DROPLIST.keys() :
             st.takeItems(DROPLIST[mobId],-1)
-        if player.getClassId().isMage() and st.getInt("onlyone") == 0:
+        if player.getClassId().isMage() :
           st.giveItems(SPIRITSHOT_NO_GRADE,500)
-          if player.getLevel() < 25 and player.isNewbie(): 
-            st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID,3000)
-        elif st.getInt("onlyone") == 0:
+        else :
           st.giveItems(SOULSHOT_NO_GRADE,1000)
+        # check the player state against this quest newbie rewarding mark.
+        newbie = player.getNewbie()
+        if newbie | NEWBIE_REWARD != newbie :
+           player.setNewbie(newbie|NEWBIE_REWARD)
+           if player.getClassId().isMage() :
+              st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS,3000)
+              st.playTutorialVoice("tutorial_voice_027")
         st.giveItems(1060,int(100*Config.RATE_QUESTS_REWARD))     # Lesser Healing Potions
-        st.giveItems(WAND_OF_ADEPT_ID,1)
+        st.giveItems(WAND_OF_ADEPT,1)
         for item in range(4412,4417) :
             st.giveItems(item,int(10*Config.RATE_QUESTS_REWARD))   # Echo crystals
         htmltext = "30017-05.htm" 
@@ -105,8 +116,8 @@ class Quest (JQuest) :
    if not st: return 
    if st.getState() != State.STARTED : return 
    npcId = npc.getNpcId() 
-   if st.getInt("cond") >= 1 and st.getItemEquipped(9) == GALLINS_OAK_WAND_ID and not st.getQuestItemsCount(DROPLIST[npcId]) : # (7) means weapon slot 
-     st.takeItems(GALLINS_OAK_WAND_ID,1) 
+   if st.getInt("cond") >= 1 and st.getItemEquipped(9) == GALLINS_OAK_WAND and not st.getQuestItemsCount(DROPLIST[npcId]) : # (7) means weapon slot 
+     st.takeItems(GALLINS_OAK_WAND,1) 
      st.giveItems(DROPLIST[npcId],1) 
      if HaveAllQuestItems(st) : 
        st.set("cond","3") 
@@ -125,4 +136,4 @@ QUEST.addTalkId(30043)
 QUEST.addTalkId(30045) 
 
 for mobId in DROPLIST.keys(): 
-  QUEST.addKillId(mobId)
+  QUEST.addKillId(mobId)

+ 89 - 74
datapack_development/data/scripts/quests/105_SkirmishWithOrcs/__init__.py

@@ -7,29 +7,37 @@ from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
 
 qn = "105_SkirmishWithOrcs" 
 
-KENDNELLS_ORDER1_ID = 1836 
-KENDNELLS_ORDER2_ID = 1837 
-KENDNELLS_ORDER3_ID = 1838 
-KENDNELLS_ORDER4_ID = 1839 
-KENDNELLS_ORDER5_ID = 1840 
-KENDNELLS_ORDER6_ID = 1841 
-KENDNELLS_ORDER7_ID = 1842 
-KENDNELLS_ORDER8_ID = 1843 
-KABOO_CHIEF_TORC1_ID = 1844 
-KABOO_CHIEF_TORC2_ID = 1845 
-RED_SUNSET_SWORD_ID = 981 
-RED_SUNSET_STAFF_ID = 754 
-SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5790 
-SPIRITSHOT_NO_GRADE_ID = 2509 
-SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5789
-SOULSHOT_NO_GRADE_ID = 1835
+KENDNELLS_ORDER1 = 1836 
+KENDNELLS_ORDER2 = 1837 
+KENDNELLS_ORDER3 = 1838 
+KENDNELLS_ORDER4 = 1839 
+KENDNELLS_ORDER5 = 1840 
+KENDNELLS_ORDER6 = 1841 
+KENDNELLS_ORDER7 = 1842 
+KENDNELLS_ORDER8 = 1843 
+KABOO_CHIEF_TORC1 = 1844 
+KABOO_CHIEF_TORC2 = 1845 
+RED_SUNSET_SWORD = 981 
+RED_SUNSET_STAFF = 754
+
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 2
+SPIRITSHOT_NO_GRADE_FOR_BEGINNERS = 5790 
+SPIRITSHOT_NO_GRADE = 2509 
+SOULSHOT_NO_GRADE_FOR_BEGINNERS = 5789
+SOULSHOT_NO_GRADE = 1835
+
 
 
 class Quest (JQuest) : 
 
  def __init__(self,id,name,descr):
      JQuest.__init__(self,id,name,descr)
-     self.questItemIds = [KENDNELLS_ORDER1_ID, KENDNELLS_ORDER2_ID, KENDNELLS_ORDER3_ID, KENDNELLS_ORDER4_ID, KENDNELLS_ORDER5_ID, KENDNELLS_ORDER6_ID, KENDNELLS_ORDER7_ID, KENDNELLS_ORDER8_ID]
+     self.questItemIds = [KENDNELLS_ORDER1, KENDNELLS_ORDER2, KENDNELLS_ORDER3, KENDNELLS_ORDER4, KENDNELLS_ORDER5, KENDNELLS_ORDER6, KENDNELLS_ORDER7, KENDNELLS_ORDER8]
 
  def onEvent (self,event,st) : 
     htmltext = event 
@@ -39,16 +47,16 @@ class Quest (JQuest) :
       st.setState(State.STARTED) 
       st.playSound("ItemSound.quest_accept") 
       htmltext = "30218-03.htm" 
-      if st.getQuestItemsCount(KENDNELLS_ORDER1_ID)+st.getQuestItemsCount(KENDNELLS_ORDER2_ID)+st.getQuestItemsCount(KENDNELLS_ORDER3_ID)+st.getQuestItemsCount(KENDNELLS_ORDER4_ID) == 0 : 
+      if st.getQuestItemsCount(KENDNELLS_ORDER1)+st.getQuestItemsCount(KENDNELLS_ORDER2)+st.getQuestItemsCount(KENDNELLS_ORDER3)+st.getQuestItemsCount(KENDNELLS_ORDER4) == 0 : 
         n = st.getRandom(100) 
         if n < 25 : 
-          st.giveItems(KENDNELLS_ORDER1_ID,1) 
+          st.giveItems(KENDNELLS_ORDER1,1) 
         elif n < 50 : 
-          st.giveItems(KENDNELLS_ORDER2_ID,1) 
+          st.giveItems(KENDNELLS_ORDER2,1) 
         elif n < 75 : 
-          st.giveItems(KENDNELLS_ORDER3_ID,1) 
+          st.giveItems(KENDNELLS_ORDER3,1) 
         else: 
-          st.giveItems(KENDNELLS_ORDER4_ID,1) 
+          st.giveItems(KENDNELLS_ORDER4,1) 
     return htmltext 
 
 
@@ -73,51 +81,58 @@ class Quest (JQuest) :
    elif npcId == 30218 and st.getInt("cond")==0 and st.getInt("onlyone")==1 : 
       htmltext = "<html><body>This quest has already been completed.</body></html>" 
    elif npcId == 30218 and st.getInt("cond") : 
-      if st.getQuestItemsCount(KABOO_CHIEF_TORC1_ID) : 
+      if st.getQuestItemsCount(KABOO_CHIEF_TORC1) : 
         htmltext = "30218-06.htm" 
-        if st.getQuestItemsCount(KENDNELLS_ORDER1_ID) : 
-          st.takeItems(KENDNELLS_ORDER1_ID,1) 
-        if st.getQuestItemsCount(KENDNELLS_ORDER2_ID) : 
-          st.takeItems(KENDNELLS_ORDER2_ID,1) 
-        if st.getQuestItemsCount(KENDNELLS_ORDER3_ID) : 
-          st.takeItems(KENDNELLS_ORDER3_ID,1) 
-        if st.getQuestItemsCount(KENDNELLS_ORDER4_ID) : 
-          st.takeItems(KENDNELLS_ORDER4_ID,1) 
-        st.takeItems(KABOO_CHIEF_TORC1_ID,1) 
+        if st.getQuestItemsCount(KENDNELLS_ORDER1) : 
+          st.takeItems(KENDNELLS_ORDER1,1) 
+        if st.getQuestItemsCount(KENDNELLS_ORDER2) : 
+          st.takeItems(KENDNELLS_ORDER2,1) 
+        if st.getQuestItemsCount(KENDNELLS_ORDER3) : 
+          st.takeItems(KENDNELLS_ORDER3,1) 
+        if st.getQuestItemsCount(KENDNELLS_ORDER4) : 
+          st.takeItems(KENDNELLS_ORDER4,1) 
+        st.takeItems(KABOO_CHIEF_TORC1,1) 
         n = st.getRandom(100) 
         if n < 25 : 
-          st.giveItems(KENDNELLS_ORDER5_ID,1) 
+          st.giveItems(KENDNELLS_ORDER5,1) 
         elif n < 50 : 
-          st.giveItems(KENDNELLS_ORDER6_ID,1) 
+          st.giveItems(KENDNELLS_ORDER6,1) 
         elif n < 75 : 
-          st.giveItems(KENDNELLS_ORDER7_ID,1) 
+          st.giveItems(KENDNELLS_ORDER7,1) 
         else: 
-          st.giveItems(KENDNELLS_ORDER8_ID,1) 
-      elif st.getQuestItemsCount(KENDNELLS_ORDER1_ID) or st.getQuestItemsCount(KENDNELLS_ORDER2_ID) or st.getQuestItemsCount(KENDNELLS_ORDER3_ID) or st.getQuestItemsCount(KENDNELLS_ORDER4_ID) : 
+          st.giveItems(KENDNELLS_ORDER8,1) 
+      elif st.getQuestItemsCount(KENDNELLS_ORDER1) or st.getQuestItemsCount(KENDNELLS_ORDER2) or st.getQuestItemsCount(KENDNELLS_ORDER3) or st.getQuestItemsCount(KENDNELLS_ORDER4) : 
         htmltext = "30218-05.htm" 
-      elif st.getQuestItemsCount(KABOO_CHIEF_TORC2_ID) : 
+      elif st.getQuestItemsCount(KABOO_CHIEF_TORC2) : 
         if st.getInt("id") != 105 :
             st.set("id","105") 
             htmltext = "30218-08.htm" 
-            if st.getQuestItemsCount(KENDNELLS_ORDER5_ID) :
-                st.takeItems(KENDNELLS_ORDER5_ID,1)
-            if st.getQuestItemsCount(KENDNELLS_ORDER6_ID) : 
-                st.takeItems(KENDNELLS_ORDER6_ID,1) 
-            if st.getQuestItemsCount(KENDNELLS_ORDER7_ID) : 
-                st.takeItems(KENDNELLS_ORDER7_ID,1) 
-            if st.getQuestItemsCount(KENDNELLS_ORDER8_ID) : 
-                st.takeItems(KENDNELLS_ORDER8_ID,1) 
-            st.takeItems(KABOO_CHIEF_TORC2_ID,1) 
-            if player.getClassId().isMage() and st.getInt("onlyone") == 0:
-                st.giveItems(RED_SUNSET_STAFF_ID,1)
-                st.giveItems(SPIRITSHOT_NO_GRADE_ID,500)
-                if player.getLevel() < 25 and player.isNewbie():
-                    st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID,3000)
-            elif st.getInt("onlyone") == 0 : 
-                st.giveItems(RED_SUNSET_SWORD_ID,1)
-                st.giveItems(SOULSHOT_NO_GRADE_ID,1000)
-                if player.getLevel() < 25 and player.isNewbie():
-                    st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID,7000)
+            if st.getQuestItemsCount(KENDNELLS_ORDER5) :
+                st.takeItems(KENDNELLS_ORDER5,1)
+            if st.getQuestItemsCount(KENDNELLS_ORDER6) : 
+                st.takeItems(KENDNELLS_ORDER6,1) 
+            if st.getQuestItemsCount(KENDNELLS_ORDER7) : 
+                st.takeItems(KENDNELLS_ORDER7,1) 
+            if st.getQuestItemsCount(KENDNELLS_ORDER8) : 
+                st.takeItems(KENDNELLS_ORDER8,1) 
+            st.takeItems(KABOO_CHIEF_TORC2,1)
+            newbie = player.getNewbie()
+            mage = player.getClassId().isMage()
+            if mage :
+               st.giveItems(RED_SUNSET_STAFF,1)
+               st.giveItems(SPIRITSHOT_NO_GRADE,500)
+            else : 
+               st.giveItems(RED_SUNSET_SWORD,1)
+               st.giveItems(SOULSHOT_NO_GRADE,1000)
+            if newbie | NEWBIE_REWARD != newbie :
+               player.setNewbie(newbie|NEWBIE_REWARD)
+               if mage :
+                  st.playTutorialVoice("tutorial_voice_027")
+                  st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS,3000)
+               else :
+                  st.playTutorialVoice("tutorial_voice_026")
+                  st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,7000)
+               st.playSound("ItemSound.quest_tutorial")
             st.giveItems(1060,int(100*Config.RATE_QUESTS_REWARD))     # Lesser Healing Potions 
             for item in range(4412,4417) : 
                 st.giveItems(item,int(10*Config.RATE_QUESTS_REWARD))   # Echo crystals 
@@ -125,7 +140,7 @@ class Quest (JQuest) :
             st.playSound("ItemSound.quest_finish") 
             st.set("onlyone","1") 
             st.set("cond","0") 
-      elif st.getQuestItemsCount(KENDNELLS_ORDER5_ID) or st.getQuestItemsCount(KENDNELLS_ORDER6_ID) or st.getQuestItemsCount(KENDNELLS_ORDER7_ID) or st.getQuestItemsCount(KENDNELLS_ORDER8_ID) : 
+      elif st.getQuestItemsCount(KENDNELLS_ORDER5) or st.getQuestItemsCount(KENDNELLS_ORDER6) or st.getQuestItemsCount(KENDNELLS_ORDER7) or st.getQuestItemsCount(KENDNELLS_ORDER8) : 
         htmltext = "30218-07.htm" 
    return htmltext 
 
@@ -137,50 +152,50 @@ class Quest (JQuest) :
    if npcId == 27059 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER1_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC1_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC1_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER1) and st.getQuestItemsCount(KABOO_CHIEF_TORC1) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC1,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27060 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER2_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC1_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC1_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER2) and st.getQuestItemsCount(KABOO_CHIEF_TORC1) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC1,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27061 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER3_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC1_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC1_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER3) and st.getQuestItemsCount(KABOO_CHIEF_TORC1) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC1,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27062 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER4_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC1_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC1_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER4) and st.getQuestItemsCount(KABOO_CHIEF_TORC1) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC1,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27064 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER5_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC2_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC2_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER5) and st.getQuestItemsCount(KABOO_CHIEF_TORC2) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC2,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27065 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER6_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC2_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC2_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER6) and st.getQuestItemsCount(KABOO_CHIEF_TORC2) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC2,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27067 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER7_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC2_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC2_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER7) and st.getQuestItemsCount(KABOO_CHIEF_TORC2) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC2,1) 
       st.playSound("ItemSound.quest_middle") 
    elif npcId == 27068 : 
     st.set("id","0") 
     if st.getInt("cond") == 1 : 
-     if st.getQuestItemsCount(KENDNELLS_ORDER8_ID) and st.getQuestItemsCount(KABOO_CHIEF_TORC2_ID) == 0 : 
-      st.giveItems(KABOO_CHIEF_TORC2_ID,1) 
+     if st.getQuestItemsCount(KENDNELLS_ORDER8) and st.getQuestItemsCount(KABOO_CHIEF_TORC2) == 0 : 
+      st.giveItems(KABOO_CHIEF_TORC2,1) 
       st.playSound("ItemSound.quest_middle") 
    return 
 

+ 20 - 7
datapack_development/data/scripts/quests/106_ForgottenTruth/__init__.py

@@ -13,6 +13,14 @@ ANCIENT_CLAY_TABLET, KARTAS_TRANSLATION, ELDRITCH_DAGGER  \
 = range(984,990)
 
 ORC = 27070
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 2
+SPIRITSHOT_FOR_BEGINNERS = 5790
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
@@ -85,12 +93,17 @@ class Quest (JQuest) :
          for item in range(4412,4417) :
                st.giveItems(item,int(10*Config.RATE_QUESTS_REWARD))
          st.giveItems(1060,int(100*Config.RATE_QUESTS_REWARD))
-         if player.getClassId().isMage() and st.getInt("onlyone") == 0:
-             st.giveItems(2509,500)
-             if player.getLevel() < 25 and player.isNewbie():
-                 st.giveItems(5790,3000)
-         elif st.getInt("onlyone") == 0:
-             st.giveItems(1835,1000)
+         if player.getClassId().isMage() :
+            st.giveItems(2509,500)
+         else :
+            st.giveItems(1835,1000)
+         # check the player state against this quest newbie rewarding mark.
+         newbie = player.getNewbie()
+         if newbie | NEWBIE_REWARD != newbie :
+            player.setNewbie(newbie|NEWBIE_REWARD)
+            if player.getClassId().isMage() :
+               st.giveItems(SPIRITSHOT_FOR_BEGINNERS,3000)
+               st.playTutorialVoice("tutorial_voice_027")
          st.unset("cond")
          st.exitQuest(False)
          st.playSound("ItemSound.quest_finish")
@@ -122,4 +135,4 @@ QUEST.addTalkId(30358)
 
 QUEST.addTalkId(30133)
 
-QUEST.addKillId(27070)
+QUEST.addKillId(27070)

+ 17 - 4
datapack_development/data/scripts/quests/107_MercilessPunishment/__init__.py

@@ -20,7 +20,14 @@ CRYSTAL_LOVE = 4413
 CRYSTAL_SOLITUDE = 4414 
 CRYSTAL_FEAST = 4415 
 CRYSTAL_CELEBRATION = 4416 
-SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5789 
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 2
+SPIRITSHOT_NO_GRADE_FOR_BEGINNERS = 5790 
+SOULSHOT_NO_GRADE_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) : 
 
@@ -111,8 +118,14 @@ class Quest (JQuest) :
             st.giveItems(CRYSTAL_SOLITUDE,int(10*Config.RATE_QUESTS_REWARD)) 
             st.giveItems(CRYSTAL_FEAST,int(10*Config.RATE_QUESTS_REWARD)) 
             st.giveItems(CRYSTAL_CELEBRATION,int(10*Config.RATE_QUESTS_REWARD))
-            if player.getLevel() < 25 and st.getInt("onlyone") == 0 and player.isNewbie():
-                st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID,7000) 
+            # check the player state against this quest newbie rewarding mark.
+            newbie = player.getNewbie()
+            if newbie | NEWBIE_REWARD != newbie :
+               player.setNewbie(newbie|NEWBIE_REWARD)
+               if player.getClassId().isMage() :
+                  st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS,3000)
+               else :
+                  st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,7000)
             st.set("cond","0") 
             st.exitQuest(False) 
             st.playSound("ItemSound.quest_finish") 
@@ -149,4 +162,4 @@ QUEST.addTalkId(30568)
 
 QUEST.addTalkId(30580) 
 
-QUEST.addKillId(27041) 
+QUEST.addKillId(27041) 

+ 123 - 112
datapack_development/data/scripts/quests/108_JumbleTumbleDiamondFuss/__init__.py

@@ -7,46 +7,52 @@ from net.sf.l2j.gameserver.model.quest.jython import QuestJython as JQuest
 
 qn = "108_JumbleTumbleDiamondFuss" 
 
-GOUPHS_CONTRACT_ID = 1559 
-REEPS_CONTRACT_ID = 1560 
-ELVEN_WINE_ID = 1561 
-BRONPS_DICE_ID = 1562 
-BRONPS_CONTRACT_ID = 1563 
-AQUAMARINE_ID = 1564 
-CHRYSOBERYL_ID = 1565 
-GEM_BOX1_ID = 1566 
-COAL_PIECE_ID = 1567 
-BRONPS_LETTER_ID = 1568 
-BERRY_TART_ID = 1569 
-BAT_DIAGRAM_ID = 1570 
-STAR_DIAMOND_ID = 1571 
-SILVERSMITH_HAMMER_ID = 1511 
-SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5789
-SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID = 5790
+GOUPHS_CONTRACT = 1559 
+REEPS_CONTRACT = 1560 
+ELVEN_WINE = 1561 
+BRONPS_DICE = 1562 
+BRONPS_CONTRACT = 1563 
+AQUAMARINE = 1564 
+CHRYSOBERYL = 1565 
+GEM_BOX1 = 1566 
+COAL_PIECE = 1567 
+BRONPS_LETTER = 1568 
+BERRY_TART = 1569 
+BAT_DIAGRAM = 1570 
+STAR_DIAMOND = 1571 
+SILVERSMITH_HAMMER = 1511
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 2
+SOULSHOT_NO_GRADE_FOR_BEGINNERS = 5789
+SPIRITSHOT_NO_GRADE_FOR_BEGINNERS = 5790
 
 
 class Quest (JQuest) : 
 
  def __init__(self,id,name,descr):
      JQuest.__init__(self,id,name,descr)
-     self.questItemIds = [GEM_BOX1_ID, STAR_DIAMOND_ID, GOUPHS_CONTRACT_ID, REEPS_CONTRACT_ID, ELVEN_WINE_ID, BRONPS_CONTRACT_ID, AQUAMARINE_ID, CHRYSOBERYL_ID, COAL_PIECE_ID, BRONPS_DICE_ID, BRONPS_LETTER_ID, BERRY_TART_ID, BAT_DIAGRAM_ID]
+     self.questItemIds = [GEM_BOX1, STAR_DIAMOND, GOUPHS_CONTRACT, REEPS_CONTRACT, ELVEN_WINE, BRONPS_CONTRACT, AQUAMARINE, CHRYSOBERYL, COAL_PIECE, BRONPS_DICE, BRONPS_LETTER, BERRY_TART, BAT_DIAGRAM]
 
  def onEvent (self,event,st) : 
     htmltext = event 
     if event == "1" : 
           htmltext = "30523-03.htm" 
-          st.giveItems(GOUPHS_CONTRACT_ID,1) 
+          st.giveItems(GOUPHS_CONTRACT,1) 
           st.set("cond","1") 
           st.setState(State.STARTED) 
           st.playSound("ItemSound.quest_accept") 
     elif event == "30555_1" : 
           htmltext = "30555-02.htm" 
-          st.takeItems(REEPS_CONTRACT_ID,1) 
-          st.giveItems(ELVEN_WINE_ID,1) 
+          st.takeItems(REEPS_CONTRACT,1) 
+          st.giveItems(ELVEN_WINE,1) 
     elif event == "30526_1" : 
           htmltext = "30526-02.htm" 
-          st.takeItems(BRONPS_DICE_ID,1) 
-          st.giveItems(BRONPS_CONTRACT_ID,1) 
+          st.takeItems(BRONPS_DICE,1) 
+          st.giveItems(BRONPS_CONTRACT,1) 
     return htmltext 
 
 
@@ -72,97 +78,102 @@ class Quest (JQuest) :
           else: 
             htmltext = "30523-01.htm" 
             st.exitQuest(1) 
-   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT_ID) : 
+   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT) : 
           htmltext = "30523-04.htm" 
-   elif npcId == 30523 and st.getInt("cond")==1 and (st.getQuestItemsCount(REEPS_CONTRACT_ID) or st.getQuestItemsCount(ELVEN_WINE_ID) or st.getQuestItemsCount(BRONPS_DICE_ID) or st.getQuestItemsCount(BRONPS_CONTRACT_ID)) : 
+   elif npcId == 30523 and st.getInt("cond")==1 and (st.getQuestItemsCount(REEPS_CONTRACT) or st.getQuestItemsCount(ELVEN_WINE) or st.getQuestItemsCount(BRONPS_DICE) or st.getQuestItemsCount(BRONPS_CONTRACT)) : 
           htmltext = "30523-05.htm" 
-   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1_ID) : 
+   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1) : 
           htmltext = "30523-06.htm" 
-          st.takeItems(GEM_BOX1_ID,1) 
-          st.giveItems(COAL_PIECE_ID,1) 
-   elif npcId == 30523 and st.getInt("cond")==1 and (st.getQuestItemsCount(BRONPS_LETTER_ID) or st.getQuestItemsCount(COAL_PIECE_ID) or st.getQuestItemsCount(BERRY_TART_ID) or st.getQuestItemsCount(BAT_DIAGRAM_ID)) : 
+          st.takeItems(GEM_BOX1,1) 
+          st.giveItems(COAL_PIECE,1) 
+   elif npcId == 30523 and st.getInt("cond")==1 and (st.getQuestItemsCount(BRONPS_LETTER) or st.getQuestItemsCount(COAL_PIECE) or st.getQuestItemsCount(BERRY_TART) or st.getQuestItemsCount(BAT_DIAGRAM)) : 
           htmltext = "30523-07.htm" 
-   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(STAR_DIAMOND_ID) : 
-            htmltext = "30523-08.htm"
-            if player.getLevel() < 25 and st.getInt("onlyone") == 0 and player.isNewbie():
-                if player.getClassId().isMage() :
-                    st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS_ID,3000)
-                else :
-                    st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS_ID,7000)
-            st.giveItems(1060,int(100*Config.RATE_QUESTS_REWARD))     # Lesser Healing Potions 
-            st.giveItems(SILVERSMITH_HAMMER_ID,1) 
-            for item in range(4412,4417) :
-                st.giveItems(item,int(10*Config.RATE_QUESTS_REWARD))   # Echo crystals
-            st.takeItems(STAR_DIAMOND_ID,-1) 
-            st.set("cond","0") 
-            st.exitQuest(False) 
-            st.playSound("ItemSound.quest_finish") 
+   elif npcId == 30523 and st.getInt("cond")==1 and st.getQuestItemsCount(STAR_DIAMOND) : 
+          htmltext = "30523-08.htm"
+          # check the player state against this quest newbie rewarding mark.
+          newbie = player.getNewbie()
+          if newbie | NEWBIE_REWARD != newbie :
+             player.setNewbie(newbie|NEWBIE_REWARD)
+             if player.getClassId().isMage() :
+                st.giveItems(SPIRITSHOT_NO_GRADE_FOR_BEGINNERS,3000)
+                st.playTutorialVoice("tutorial_voice_027")
+             else :
+                st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,7000)
+                st.playTutorialVoice("tutorial_voice_026")
+          st.giveItems(1060,int(100*Config.RATE_QUESTS_REWARD))     # Lesser Healing Potions 
+          st.giveItems(SILVERSMITH_HAMMER,1) 
+          for item in range(4412,4417) :
+              st.giveItems(item,int(10*Config.RATE_QUESTS_REWARD))   # Echo crystals
+          st.takeItems(STAR_DIAMOND,-1) 
+          st.set("cond","0") 
+          st.exitQuest(False) 
+          st.playSound("ItemSound.quest_finish") 
    elif id == State.STARTED : 
-       if npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT_ID) and st.getQuestItemsCount(REEPS_CONTRACT_ID)==0 : 
+       if npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT) and st.getQuestItemsCount(REEPS_CONTRACT)==0 : 
               htmltext = "30516-01.htm" 
-              st.giveItems(REEPS_CONTRACT_ID,1) 
-              st.takeItems(GOUPHS_CONTRACT_ID,1) 
-       elif npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT_ID)==0 and st.getQuestItemsCount(REEPS_CONTRACT_ID) : 
+              st.giveItems(REEPS_CONTRACT,1) 
+              st.takeItems(GOUPHS_CONTRACT,1) 
+       elif npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT)==0 and st.getQuestItemsCount(REEPS_CONTRACT) : 
               htmltext = "30516-02.htm" 
-       elif npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT_ID)==0 and st.getQuestItemsCount(REEPS_CONTRACT_ID)==0 : 
+       elif npcId == 30516 and st.getInt("cond")==1 and st.getQuestItemsCount(GOUPHS_CONTRACT)==0 and st.getQuestItemsCount(REEPS_CONTRACT)==0 : 
               htmltext = "30516-03.htm" 
-       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT_ID)==0 and st.getQuestItemsCount(ELVEN_WINE_ID)==0 : 
+       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT)==0 and st.getQuestItemsCount(ELVEN_WINE)==0 : 
               htmltext = "30555-01.htm" 
-       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT_ID) and st.getQuestItemsCount(ELVEN_WINE_ID)==0 : 
+       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT) and st.getQuestItemsCount(ELVEN_WINE)==0 : 
               htmltext = "30555-02.htm" 
-              st.giveItems(ELVEN_WINE_ID,1) 
-              st.takeItems(REEPS_CONTRACT_ID,1) 
-       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT_ID)==0 and st.getQuestItemsCount(ELVEN_WINE_ID) : 
+              st.giveItems(ELVEN_WINE,1) 
+              st.takeItems(REEPS_CONTRACT,1) 
+       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(REEPS_CONTRACT)==0 and st.getQuestItemsCount(ELVEN_WINE) : 
               htmltext = "30555-03.htm" 
-       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1_ID)==1 : 
+       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1)==1 : 
               htmltext = "30555-04.htm" 
-       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1_ID)==0 and st.getQuestItemsCount(REEPS_CONTRACT_ID)==0 and st.getQuestItemsCount(ELVEN_WINE_ID)==0 : 
+       elif npcId == 30555 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1)==0 and st.getQuestItemsCount(REEPS_CONTRACT)==0 and st.getQuestItemsCount(ELVEN_WINE)==0 : 
               htmltext = "30555-05.htm" 
-       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE_ID) and st.getQuestItemsCount(BRONPS_DICE_ID)==0 : 
+       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE) and st.getQuestItemsCount(BRONPS_DICE)==0 : 
               htmltext = "30529-01.htm" 
-              st.giveItems(BRONPS_DICE_ID,1) 
-              st.takeItems(ELVEN_WINE_ID,1) 
-       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE_ID)==0 and st.getQuestItemsCount(BRONPS_DICE_ID) : 
+              st.giveItems(BRONPS_DICE,1) 
+              st.takeItems(ELVEN_WINE,1) 
+       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE)==0 and st.getQuestItemsCount(BRONPS_DICE) : 
               htmltext = "30529-02.htm" 
-       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE_ID)==0 and st.getQuestItemsCount(BRONPS_DICE_ID)==0 : 
+       elif npcId == 30529 and st.getInt("cond")==1 and st.getQuestItemsCount(ELVEN_WINE)==0 and st.getQuestItemsCount(BRONPS_DICE)==0 : 
               htmltext = "30529-03.htm" 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_DICE_ID) : 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_DICE) : 
               htmltext = "30526-01.htm" 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_CONTRACT_ID) and (st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID)<20) : 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_CONTRACT) and (st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL)<20) : 
               htmltext = "30526-03.htm" 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_CONTRACT_ID) and (st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID)>=20) : 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_CONTRACT) and (st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL)>=20) : 
               htmltext = "30526-04.htm" 
-              st.takeItems(BRONPS_CONTRACT_ID,1) 
-              st.takeItems(AQUAMARINE_ID,st.getQuestItemsCount(AQUAMARINE_ID)) 
-              st.takeItems(CHRYSOBERYL_ID,st.getQuestItemsCount(CHRYSOBERYL_ID)) 
-              st.giveItems(GEM_BOX1_ID,1) 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1_ID) : 
+              st.takeItems(BRONPS_CONTRACT,1) 
+              st.takeItems(AQUAMARINE,st.getQuestItemsCount(AQUAMARINE)) 
+              st.takeItems(CHRYSOBERYL,st.getQuestItemsCount(CHRYSOBERYL)) 
+              st.giveItems(GEM_BOX1,1) 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(GEM_BOX1) : 
               htmltext = "30526-05.htm" 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(COAL_PIECE_ID) : 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(COAL_PIECE) : 
               htmltext = "30526-06.htm" 
-              st.takeItems(COAL_PIECE_ID,1) 
-              st.giveItems(BRONPS_LETTER_ID,1) 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER_ID) : 
+              st.takeItems(COAL_PIECE,1) 
+              st.giveItems(BRONPS_LETTER,1) 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER) : 
               htmltext = "30526-07.htm" 
-       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BERRY_TART_ID) or st.getQuestItemsCount(BAT_DIAGRAM_ID) or st.getQuestItemsCount(STAR_DIAMOND_ID) : 
+       elif npcId == 30526 and st.getInt("cond")==1 and st.getQuestItemsCount(BERRY_TART) or st.getQuestItemsCount(BAT_DIAGRAM) or st.getQuestItemsCount(STAR_DIAMOND) : 
               htmltext = "30526-08.htm" 
-       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER_ID) and st.getQuestItemsCount(BERRY_TART_ID)==0 : 
+       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER) and st.getQuestItemsCount(BERRY_TART)==0 : 
               htmltext = "30521-01.htm" 
-              st.giveItems(BERRY_TART_ID,1) 
-              st.takeItems(BRONPS_LETTER_ID,1) 
-       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER_ID)==0 and st.getQuestItemsCount(BERRY_TART_ID) : 
+              st.giveItems(BERRY_TART,1) 
+              st.takeItems(BRONPS_LETTER,1) 
+       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER)==0 and st.getQuestItemsCount(BERRY_TART) : 
               htmltext = "30521-02.htm" 
-       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER_ID)==0 and st.getQuestItemsCount(BERRY_TART_ID)==0 : 
+       elif npcId == 30521 and st.getInt("cond")==1 and st.getQuestItemsCount(BRONPS_LETTER)==0 and st.getQuestItemsCount(BERRY_TART)==0 : 
               htmltext = "30521-03.htm" 
-       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM_ID)==0 and st.getQuestItemsCount(BERRY_TART_ID) and st.getQuestItemsCount(STAR_DIAMOND_ID)==0 : 
+       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM)==0 and st.getQuestItemsCount(BERRY_TART) and st.getQuestItemsCount(STAR_DIAMOND)==0 : 
               htmltext = "30522-01.htm" 
-              st.giveItems(BAT_DIAGRAM_ID,1) 
-              st.takeItems(BERRY_TART_ID,1) 
-       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM_ID) and st.getQuestItemsCount(BERRY_TART_ID)==0 and st.getQuestItemsCount(STAR_DIAMOND_ID)==0 : 
+              st.giveItems(BAT_DIAGRAM,1) 
+              st.takeItems(BERRY_TART,1) 
+       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM) and st.getQuestItemsCount(BERRY_TART)==0 and st.getQuestItemsCount(STAR_DIAMOND)==0 : 
               htmltext = "30522-02.htm" 
-       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM_ID)==0 and st.getQuestItemsCount(BERRY_TART_ID)==0 and st.getQuestItemsCount(STAR_DIAMOND_ID) : 
+       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM)==0 and st.getQuestItemsCount(BERRY_TART)==0 and st.getQuestItemsCount(STAR_DIAMOND) : 
               htmltext = "30522-03.htm" 
-       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM_ID)==0 and st.getQuestItemsCount(BERRY_TART_ID)==0 and st.getQuestItemsCount(STAR_DIAMOND_ID)==0 : 
+       elif npcId == 30522 and st.getInt("cond")==1 and st.getQuestItemsCount(BAT_DIAGRAM)==0 and st.getQuestItemsCount(BERRY_TART)==0 and st.getQuestItemsCount(STAR_DIAMOND)==0 : 
               htmltext = "30522-04.htm" 
    return htmltext 
 
@@ -173,50 +184,50 @@ class Quest (JQuest) :
 
    npcId = npc.getNpcId() 
    if npcId == 20323 : 
-        if st.getInt("cond") == 1 and st.getQuestItemsCount(BRONPS_CONTRACT_ID) : 
+        if st.getInt("cond") == 1 and st.getQuestItemsCount(BRONPS_CONTRACT) : 
           if st.getRandom(10) < 8 : 
-            if st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) == 19 : 
-              if st.getQuestItemsCount(AQUAMARINE_ID) < 10 : 
-                st.giveItems(AQUAMARINE_ID,1) 
+            if st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) == 19 : 
+              if st.getQuestItemsCount(AQUAMARINE) < 10 : 
+                st.giveItems(AQUAMARINE,1) 
                 st.playSound("ItemSound.quest_middle") 
             else: 
-              if st.getQuestItemsCount(AQUAMARINE_ID) < 10 : 
-                st.giveItems(AQUAMARINE_ID,1) 
+              if st.getQuestItemsCount(AQUAMARINE) < 10 : 
+                st.giveItems(AQUAMARINE,1) 
                 st.playSound("ItemSound.quest_itemget") 
           if st.getRandom(10) < 8 : 
-            if st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) == 19 : 
-              if st.getQuestItemsCount(CHRYSOBERYL_ID) < 10 : 
-                st.giveItems(CHRYSOBERYL_ID,1) 
+            if st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) == 19 : 
+              if st.getQuestItemsCount(CHRYSOBERYL) < 10 : 
+                st.giveItems(CHRYSOBERYL,1) 
                 st.playSound("ItemSound.quest_middle") 
-            elif st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) < 20 : 
-                if st.getQuestItemsCount(CHRYSOBERYL_ID) < 10 : 
-                  st.giveItems(CHRYSOBERYL_ID,1) 
+            elif st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) < 20 : 
+                if st.getQuestItemsCount(CHRYSOBERYL) < 10 : 
+                  st.giveItems(CHRYSOBERYL,1) 
                   st.playSound("ItemSound.quest_itemget") 
    elif npcId == 20324 : 
-        if st.getInt("cond") == 1 and st.getQuestItemsCount(BRONPS_CONTRACT_ID) : 
+        if st.getInt("cond") == 1 and st.getQuestItemsCount(BRONPS_CONTRACT) : 
           if st.getRandom(10) < 6 : 
-            if st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) == 19 : 
-              if st.getQuestItemsCount(AQUAMARINE_ID) < 10 : 
-                st.giveItems(AQUAMARINE_ID,1) 
+            if st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) == 19 : 
+              if st.getQuestItemsCount(AQUAMARINE) < 10 : 
+                st.giveItems(AQUAMARINE,1) 
                 st.playSound("ItemSound.quest_middle") 
             else: 
-              if st.getQuestItemsCount(AQUAMARINE_ID) < 10 : 
-                st.giveItems(AQUAMARINE_ID,1) 
+              if st.getQuestItemsCount(AQUAMARINE) < 10 : 
+                st.giveItems(AQUAMARINE,1) 
                 st.playSound("ItemSound.quest_itemget") 
           if st.getRandom(10) < 6 : 
-            if st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) == 19 : 
-              if st.getQuestItemsCount(CHRYSOBERYL_ID) < 10 : 
-                st.giveItems(CHRYSOBERYL_ID,1) 
+            if st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) == 19 : 
+              if st.getQuestItemsCount(CHRYSOBERYL) < 10 : 
+                st.giveItems(CHRYSOBERYL,1) 
                 st.playSound("ItemSound.quest_middle") 
-            elif st.getQuestItemsCount(AQUAMARINE_ID)+st.getQuestItemsCount(CHRYSOBERYL_ID) < 20 : 
-                if st.getQuestItemsCount(CHRYSOBERYL_ID) < 10 : 
-                  st.giveItems(CHRYSOBERYL_ID,1) 
+            elif st.getQuestItemsCount(AQUAMARINE)+st.getQuestItemsCount(CHRYSOBERYL) < 20 : 
+                if st.getQuestItemsCount(CHRYSOBERYL) < 10 : 
+                  st.giveItems(CHRYSOBERYL,1) 
                   st.playSound("ItemSound.quest_itemget") 
    elif npcId == 20480 : 
-        if st.getInt("cond") == 1 and st.getQuestItemsCount(BAT_DIAGRAM_ID) and st.getQuestItemsCount(STAR_DIAMOND_ID) == 0 : 
+        if st.getInt("cond") == 1 and st.getQuestItemsCount(BAT_DIAGRAM) and st.getQuestItemsCount(STAR_DIAMOND) == 0 : 
           if st.getRandom(10) < 2 : 
-            st.giveItems(STAR_DIAMOND_ID,1) 
-            st.takeItems(BAT_DIAGRAM_ID,1) 
+            st.giveItems(STAR_DIAMOND,1) 
+            st.takeItems(BAT_DIAGRAM,1) 
             st.playSound("ItemSound.quest_middle") 
    return 
 
@@ -236,4 +247,4 @@ QUEST.addTalkId(30555)
 
 QUEST.addKillId(20323) 
 QUEST.addKillId(20324) 
-QUEST.addKillId(20480) 
+QUEST.addKillId(20480) 

+ 20 - 1
datapack_development/data/scripts/quests/257_GuardIsBusy1/__init__.py

@@ -11,6 +11,14 @@ ORC_AMULET = 752
 ORC_NECKLACE = 1085
 WEREWOLF_FANG = 1086
 ADENA = 57
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 4
+SPIRITSHOT_FOR_BEGINNERS = 5790
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
@@ -53,6 +61,17 @@ class Quest (JQuest) :
      if orc_a==orc_n==wer_f==0 :
        htmltext = "30039-04.htm"
      else :
+       # check the player state against this quest newbie rewarding mark.
+       newbie = player.getNewbie()
+       if newbie | NEWBIE_REWARD != newbie :
+          player.setNewbie(newbie|NEWBIE_REWARD)
+          st.showQuestionMark(26)
+          if player.getClassId().isMage() :
+             st.playTutorialVoice("tutorial_voice_027")
+             st.giveItems(SPIRITSHOT_FOR_BEGINNERS,3000)
+          else :
+             st.playTutorialVoice("tutorial_voice_026")
+             st.giveItems(SOULSHOT_FOR_BEGINNERS,6000)
        st.giveItems(ADENA,5*orc_a+15*orc_n+10*wer_f)
        st.takeItems(ORC_AMULET,-1)
        st.takeItems(ORC_NECKLACE,-1)
@@ -95,4 +114,4 @@ QUEST.addKillId(20343)
 QUEST.addKillId(20006)
 QUEST.addKillId(20093)
 QUEST.addKillId(20096)
-QUEST.addKillId(20098)
+QUEST.addKillId(20098)

+ 20 - 1
datapack_development/data/scripts/quests/260_HuntForOrcs1/__init__.py

@@ -9,6 +9,14 @@ qn = "260_HuntForOrcs1"
 ORC_AMULET = 1114
 ORC_NECKLACE = 1115
 ADENA = 57
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 4
+SPIRITSHOT_FOR_BEGINNERS = 5790
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
@@ -56,6 +64,17 @@ class Quest (JQuest) :
        st.giveItems(ADENA,amulet*5+necklace*15)
        st.takeItems(ORC_AMULET,-1)
        st.takeItems(ORC_NECKLACE,-1)
+       # check the player state against this quest newbie rewarding mark.
+       newbie = player.getNewbie()
+       if newbie | NEWBIE_REWARD != newbie :
+          player.setNewbie(newbie|NEWBIE_REWARD)
+          st.showQuestionMark(26)
+          if player.getClassId().isMage() :
+             st.playTutorialVoice("tutorial_voice_027")
+             st.giveItems(SPIRITSHOT_FOR_BEGINNERS,3000)
+          else :
+             st.playTutorialVoice("tutorial_voice_026")
+             st.giveItems(SOULSHOT_FOR_BEGINNERS,6000)
    return htmltext
 
  def onKill(self,npc,player,isPet):
@@ -82,4 +101,4 @@ QUEST.addKillId(20469)
 QUEST.addKillId(20470)
 QUEST.addKillId(20471)
 QUEST.addKillId(20472)
-QUEST.addKillId(20473)
+QUEST.addKillId(20473)

+ 20 - 1
datapack_development/data/scripts/quests/265_ChainsOfSlavery/__init__.py

@@ -8,6 +8,14 @@ qn = "265_ChainsOfSlavery"
 
 IMP_SHACKLES = 1368
 ADENA = 57
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 4
+SPIRITSHOT_FOR_BEGINNERS = 5790
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
@@ -54,6 +62,17 @@ class Quest (JQuest) :
        else :
           st.giveItems(ADENA,13*count)
        st.takeItems(IMP_SHACKLES,-1)
+       # check the player state against this quest newbie rewarding mark.
+       newbie = player.getNewbie()
+       if newbie | NEWBIE_REWARD != newbie :
+          player.setNewbie(newbie|NEWBIE_REWARD)
+          st.showQuestionMark(26)
+          if player.getClassId().isMage() :
+             st.playTutorialVoice("tutorial_voice_027")
+             st.giveItems(SPIRITSHOT_FOR_BEGINNERS,3000)
+          else :
+             st.playTutorialVoice("tutorial_voice_026")
+             st.giveItems(SOULSHOT_FOR_BEGINNERS,6000)
        htmltext = "30357-05.htm"
      else:
        htmltext = "30357-04.htm"
@@ -76,4 +95,4 @@ QUEST.addStartNpc(30357)
 QUEST.addTalkId(30357)
 
 QUEST.addKillId(20004)
-QUEST.addKillId(20005)
+QUEST.addKillId(20005)

+ 16 - 1
datapack_development/data/scripts/quests/273_InvadersOfHolyland/__init__.py

@@ -9,6 +9,13 @@ qn = "273_InvadersOfHolyland"
 BLACK_SOULSTONE = 1475
 RED_SOULSTONE = 1476
 ADENA = 57
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 4
+SOULSHOT_FOR_BEGINNERS = 5789
 
 class Quest (JQuest) :
 
@@ -71,6 +78,14 @@ class Quest (JQuest) :
         st.takeItems(RED_SOULSTONE,red)
         st.giveItems(ADENA,amount)
         st.playSound("ItemSound.quest_finish")
+     if red+black != 0 :
+        # check the player state against this quest newbie rewarding mark.
+       newbie = player.getNewbie()
+       if newbie | NEWBIE_REWARD != newbie :
+          player.setNewbie(newbie|NEWBIE_REWARD)
+          st.showQuestionMark(26)
+          st.playTutorialVoice("tutorial_voice_026")
+          st.giveItems(SOULSHOT_FOR_BEGINNERS,6000)
    return htmltext
 
  def onKill(self,npc,player,isPet):
@@ -97,4 +112,4 @@ QUEST.addTalkId(30566)
 
 QUEST.addKillId(20311)
 QUEST.addKillId(20312)
-QUEST.addKillId(20313)
+QUEST.addKillId(20313)

+ 22 - 1
datapack_development/data/scripts/quests/293_HiddenVein/__init__.py

@@ -11,6 +11,24 @@ TORN_MAP_FRAGMENT = 1489
 HIDDEN_VEIN_MAP = 1490
 ADENA = 57
 
+#Newbie/one time rewards section
+#Any quest should rely on a unique bit, but
+#it could be shared among quest that were mutually
+#exclusive or race restricted.
+#Bit #1 isn't used for backwards compatibility.
+NEWBIE_REWARD = 4
+SOULSHOT_FOR_BEGINNERS = 5789
+
+def newbie_rewards(st) :
+  # check the player state against this quest newbie rewarding mark.
+  player=st.getPlayer()
+  newbie = player.getNewbie()
+  if newbie | NEWBIE_REWARD != newbie :
+     player.setNewbie(newbie|NEWBIE_REWARD)
+     st.giveItems(SOULSHOT_NO_GRADE_FOR_BEGINNERS,6000)
+     st.playTutorialVoice("tutorial_voice_026")
+  
+
 class Quest (JQuest) :
 
  def __init__(self,id,name,descr):
@@ -61,15 +79,18 @@ class Quest (JQuest) :
          if st.getQuestItemsCount(HIDDEN_VEIN_MAP)==0 :
            htmltext = "30535-04.htm"
          else :
+           newbie_rewards(st)
            htmltext = "30535-08.htm"
            st.giveItems(ADENA,st.getQuestItemsCount(HIDDEN_VEIN_MAP)*1000)
            st.takeItems(HIDDEN_VEIN_MAP,-1)
        else :
          if st.getQuestItemsCount(HIDDEN_VEIN_MAP)==0 :
+           newbie_rewards(st)
            htmltext = "30535-05.htm"
            st.giveItems(ADENA,st.getQuestItemsCount(CHRYSOLITE_ORE)*10)
            st.takeItems(CHRYSOLITE_ORE,-1)
          else :
+           newbie_rewards(st)
            htmltext = "30535-09.htm"
            st.giveItems(ADENA,st.getQuestItemsCount(CHRYSOLITE_ORE)*10+st.getQuestItemsCount(HIDDEN_VEIN_MAP)*1000)
            st.takeItems(HIDDEN_VEIN_MAP,-1)
@@ -102,4 +123,4 @@ QUEST.addTalkId(30539)
 
 QUEST.addKillId(20446)
 QUEST.addKillId(20447)
-QUEST.addKillId(20448)
+QUEST.addKillId(20448)

+ 56 - 56
datapack_development/sql/characters.sql

@@ -2,62 +2,62 @@
 -- Table structure for characters
 -- ---------------------------
 CREATE TABLE IF NOT EXISTS characters (
-  account_name varchar(45) default NULL,
-  obj_Id decimal(11,0) NOT NULL default '0',
-  char_name varchar(35) NOT NULL,
-  `level` decimal(11,0) default NULL,
-  maxHp decimal(11,0) default NULL,
-  curHp decimal(18,0) default NULL,
-  maxCp decimal(11,0) default NULL,
-  curCp decimal(18,0) default NULL,
-  maxMp decimal(11,0) default NULL,
-  curMp decimal(18,0) default NULL,
-  face decimal(11,0) default NULL,
-  hairStyle decimal(11,0) default NULL,
-  hairColor decimal(11,0) default NULL,
-  sex decimal(11,0) default NULL,
-  heading decimal(11,0) default NULL,
-  x decimal(11,0) default NULL,
-  y decimal(11,0) default NULL,
-  z decimal(11,0) default NULL,
-  exp decimal(20,0) default NULL,
-  expBeforeDeath decimal(20,0) default 0,
-  sp decimal(11,0) default NULL,
-  karma decimal(11,0) default NULL,
-  pvpkills decimal(11,0) default NULL,
-  pkkills decimal(11,0) default NULL,
-  clanid decimal(11,0) default NULL,
-  race decimal(11,0) default NULL,
-  classid decimal(11,0) default NULL,
-  base_class int(2) NOT NULL default '0',
-  transform_id int(8) NOT NULL default '0',
-  deletetime decimal(20,0) default NULL,
-  cancraft decimal(11,0) default NULL,
-  title varchar(16) default NULL,
-  rec_have int(3) NOT NULL default '0',
-  rec_left int(3) NOT NULL default '0',
-  accesslevel decimal(4,0) default NULL,
-  online decimal(1,0) default NULL,
-  onlinetime decimal(20,0) default NULL,
-  char_slot decimal(1) default NULL,
-  newbie decimal(1,0) default '1',
-  lastAccess decimal(20,0) default NULL,
-  clan_privs INT DEFAULT 0,
-  wantspeace decimal(1,0) DEFAULT 0,
-  isin7sdungeon decimal(1,0) NOT NULL default 0,
-  in_jail decimal(1,0) DEFAULT 0,
-  jail_timer decimal(20,0) DEFAULT 0,
-  power_grade decimal(11,0) DEFAULT NULL,
-  nobless decimal(1,0) NOT NULL DEFAULT 0,
-  subpledge int(1) NOT NULL DEFAULT 0,
-  last_recom_date decimal(20,0) NOT NULL DEFAULT 0,
-  lvl_joined_academy int(1) NOT NULL DEFAULT 0,
-  apprentice int(1) NOT NULL DEFAULT 0,
-  sponsor int(1) NOT NULL DEFAULT 0,
-  varka_ketra_ally int(1) NOT NULL DEFAULT 0,
-  clan_join_expiry_time DECIMAL(20,0) NOT NULL DEFAULT 0,
-  clan_create_expiry_time DECIMAL(20,0) NOT NULL DEFAULT 0,
-  death_penalty_level int(2) NOT NULL DEFAULT 0,
+  account_name VARCHAR(45) DEFAULT NULL,
+  obj_Id INT UNSIGNED NOT NULL DEFAULT 0,
+  char_name VARCHAR(35) NOT NULL,
+  level TINYINT UNSIGNED DEFAULT NULL,
+  maxHp MEDIUMINT UNSIGNED DEFAULT NULL,
+  curHp MEDIUMINT UNSIGNED DEFAULT NULL,
+  maxCp MEDIUMINT UNSIGNED DEFAULT NULL,
+  curCp MEDIUMINT UNSIGNED DEFAULT NULL,
+  maxMp MEDIUMINT UNSIGNED DEFAULT NULL,
+  curMp MEDIUMINT UNSIGNED DEFAULT NULL,
+  face TINYINT UNSIGNED DEFAULT NULL,
+  hairStyle TINYINT UNSIGNED DEFAULT NULL,
+  hairColor TINYINT UNSIGNED DEFAULT NULL,
+  sex TINYINT UNSIGNED DEFAULT NULL,
+  heading MEDIUMINT DEFAULT NULL,
+  x MEDIUMINT DEFAULT NULL,
+  y MEDIUMINT DEFAULT NULL,
+  z MEDIUMINT DEFAULT NULL,
+  exp INT UNSIGNED DEFAULT 0,
+  expBeforeDeath MEDIUMINT UNSIGNED DEFAULT 0,
+  sp INT UNSIGNED NOT NULL DEFAULT 0,
+  karma SMALLINT UNSIGNED DEFAULT NULL,
+  pvpkills SMALLINT UNSIGNED DEFAULT NULL,
+  pkkills SMALLINT UNSIGNED DEFAULT NULL,
+  clanid INT UNSIGNED DEFAULT NULL,
+  race TINYINT UNSIGNED DEFAULT NULL,
+  classid TINYINT UNSIGNED DEFAULT NULL,
+  base_class TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  transform_id SMALLINT UNSIGNED NOT NULL DEFAULT 0,
+  deletetime INT DEFAULT NULL,
+  cancraft TINYINT UNSIGNED DEFAULT NULL,
+  title VARCHAR(16) DEFAULT NULL,
+  rec_have TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  rec_left TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  accesslevel MEDIUMINT DEFAULT 0,
+  online TINYINT UNSIGNED DEFAULT NULL,
+  onlinetime INT DEFAULT NULL,
+  char_slot TINYINT UNSIGNED DEFAULT NULL,
+  newbie MEDIUMINT UNSIGNED DEFAULT 1,
+  lastAccess BIGINT UNSIGNED DEFAULT NULL,
+  clan_privs MEDIUMINT UNSIGNED DEFAULT 0,
+  wantspeace TINYINT UNSIGNED DEFAULT 0,
+  isin7sdungeon TINYINT UNSIGNED NOT NULL default 0,
+  in_jail TINYINT UNSIGNED DEFAULT 0,
+  jail_timer INT UNSIGNED DEFAULT 0,
+  power_grade TINYINT UNSIGNED DEFAULT NULL,
+  nobless TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  subpledge TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  last_recom_date BIGINT UNSIGNED NOT NULL DEFAULT 0,
+  lvl_joined_academy TINYINT UNSIGNED NOT NULL DEFAULT 0,
+  apprentice INT UNSIGNED NOT NULL DEFAULT 0,
+  sponsor INT UNSIGNED NOT NULL DEFAULT 0,
+  varka_ketra_ally TINYINT NOT NULL DEFAULT 0,
+  clan_join_expiry_time BIGINT UNSIGNED NOT NULL DEFAULT 0,
+  clan_create_expiry_time BIGINT UNSIGNED NOT NULL DEFAULT 0,
+  death_penalty_level SMALLINT UNSIGNED NOT NULL DEFAULT 0,
   PRIMARY KEY  (obj_Id),
   KEY `clanid` (`clanid`)
 ) ;

+ 22 - 0
datapack_development/sql/maintenance/20080213maintenance.sql

@@ -0,0 +1,22 @@
+-- These queries will cleanup your tables from an already
+-- fixed bug where a player that deleted a friend
+-- stood in the ex-friend contacts list.
+-- 
+-- If your L2J server setup was born after Core release 1711
+-- you won't need to run this script. Else you might want to
+-- run it just once. (Running it again shouldn't have any
+-- effect.)
+
+CREATE TABLE tmp_friends(char_id INT, friend_id INT);
+
+INSERT INTO tmp_friends
+(char_id, friend_id)
+SELECT CF1.char_id, CF1.friend_id FROM character_friends AS CF1 WHERE CF1.char_id NOT IN 
+(SELECT CF2.friend_id FROM character_friends AS CF2 WHERE CF2.char_id = CF1.friend_id);
+
+DELETE FROM character_friends using character_friends 
+INNER JOIN tmp_friends AS TF
+ON character_friends.char_id = TF.char_id
+AND character_friends.friend_id = TF.friend_id;
+
+DROP TABLE tmp_friends;

+ 23 - 0
datapack_development/sql/maintenance/documentation.txt

@@ -0,0 +1,23 @@
+There are SQL sequences that should not neccessarily be performed every time you
+update your database structure. Rather, these queries should be executed once or
+from time to time. Essentially, an .sql file should appear under 'maintenance'
+instead of the old 'updates' folder provided that:
+
+- Its execution isn't mandatory to keep L2J setups working past any core revision
+number. (e.g. orphans cleanup)
+
+- Its execution were time consuming and could slowdown regular database update tasks.
+(e.g. complex sub/queries, joins)
+
+- Its execution could allow administrators to perform optimization, maintenance, 
+repair or recovery tasks whenever they needed to.
+
+Any SQL maintenance should be named like that:
+
+YYYYMMDDmaintenance(_s).sql
+
+See the updates directory documentation for further details of the naming convention.
+
+Additionally, it would be desirable that any maintenance script could hold internal
+documentation describing their specific purpose, execution scenario and any other
+information that could be of interest for the administrator.

+ 57 - 0
datapack_development/sql/updates/20080218update.sql

@@ -0,0 +1,57 @@
+ALTER TABLE characters 
+CHANGE `account_name` `account_name` VARCHAR(45) DEFAULT NULL,
+CHANGE `obj_Id` `obj_Id` INT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `char_name` `char_name` VARCHAR(35) NOT NULL,
+CHANGE `level` `level` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `maxHp` `maxHp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `curHp` `curHp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `maxCp` `maxCp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `curCp` `curCp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `maxMp` `maxMp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `curMp` `curMp` MEDIUMINT UNSIGNED DEFAULT NULL,
+CHANGE `face` `face` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `hairStyle` `hairStyle` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `hairColor` `hairColor` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `sex` `sex` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `heading` `heading` MEDIUMINT DEFAULT NULL,
+CHANGE `x` `x` MEDIUMINT DEFAULT NULL,
+CHANGE `y` `y` MEDIUMINT DEFAULT NULL,
+CHANGE `z` `z` MEDIUMINT DEFAULT NULL,
+CHANGE `exp` `exp` INT UNSIGNED DEFAULT 0,
+CHANGE `expBeforeDeath` `expBeforeDeath` MEDIUMINT UNSIGNED DEFAULT 0,
+CHANGE `sp` `sp` INT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `karma` `karma` SMALLINT UNSIGNED DEFAULT NULL,
+CHANGE `pvpkills` `pvpkills` SMALLINT UNSIGNED DEFAULT NULL,
+CHANGE `pkkills` `pkkills` SMALLINT UNSIGNED DEFAULT NULL,
+CHANGE `clanid` `clanid` INT UNSIGNED DEFAULT NULL,
+CHANGE `race` `race` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `classid` `classid` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `base_class` `base_class` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `transform_id` `transform_id` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `deletetime` `deletetime` INT DEFAULT NULL,
+CHANGE `cancraft` `cancraft` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `title` `title` VARCHAR(16) DEFAULT NULL,
+CHANGE `rec_have` `rec_have` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `rec_left` `rec_left` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `accesslevel` `accesslevel` MEDIUMINT DEFAULT 0,
+CHANGE `online` `online` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `onlinetime` `onlinetime` INT DEFAULT NULL,
+CHANGE `char_slot` `char_slot` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `newbie` `newbie` MEDIUMINT UNSIGNED DEFAULT 1,
+CHANGE `lastAccess` `lastAccess` BIGINT UNSIGNED DEFAULT NULL,
+CHANGE `clan_privs` `clan_privs` MEDIUMINT UNSIGNED DEFAULT 0,
+CHANGE `wantspeace` `wantspeace` TINYINT UNSIGNED DEFAULT 0,
+CHANGE `isin7sdungeon` `isin7sdungeon` TINYINT UNSIGNED NOT NULL default 0,
+CHANGE `in_jail` `in_jail` TINYINT UNSIGNED DEFAULT 0,
+CHANGE `jail_timer` `jail_timer` INT UNSIGNED DEFAULT 0,
+CHANGE `power_grade` `power_grade` TINYINT UNSIGNED DEFAULT NULL,
+CHANGE `nobless` `nobless` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `subpledge` `subpledge` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `last_recom_date` `last_recom_date` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `lvl_joined_academy` `lvl_joined_academy` TINYINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `apprentice` `apprentice` INT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `sponsor` `sponsor` INT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `varka_ketra_ally` `varka_ketra_ally` TINYINT NOT NULL DEFAULT 0,
+CHANGE `clan_join_expiry_time` `clan_join_expiry_time` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `clan_create_expiry_time` `clan_create_expiry_time` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+CHANGE `death_penalty_level` `death_penalty_level` SMALLINT UNSIGNED NOT NULL DEFAULT 0 ;

+ 0 - 12
datapack_development/sql/updates/2008022008.sql

@@ -1,12 +0,0 @@
-create table tmp_friends(char_id int, friend_id int);
-
-insert into tmp_friends
-(char_id, friend_id)
-select CF1.char_id, CF1.friend_id from character_friends CF1 where CF1.char_id not in (select CF2.friend_id from character_friends CF2 where CF2.char_id = CF1.friend_id);
-
-delete from character_friends using character_friends 
-inner join tmp_friends TF
-On character_friends.char_id = TF.char_id
-and character_friends.friend_id = TF.friend_id;
-
-drop table tmp_friends;