summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/chrif.c2
-rw-r--r--src/map/clif.c91
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/intif.c39
-rw-r--r--src/map/intif.h1
-rw-r--r--src/map/map.c2
-rw-r--r--src/map/mob.c4
-rw-r--r--src/map/pc.h6
-rw-r--r--src/map/quest.c303
-rw-r--r--src/map/quest.h27
-rw-r--r--src/map/script.c77
11 files changed, 372 insertions, 183 deletions
diff --git a/src/map/chrif.c b/src/map/chrif.c
index aba1accee..63aa5dac0 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -288,6 +288,8 @@ int chrif_save(struct map_session_data *sd, int flag)
merc_save(sd->hd);
if( sd->md && mercenary_get_lifetime(sd->md) > 0 )
mercenary_save(sd->md);
+ if( sd->num_quests )
+ quest_save(sd);
return 0;
}
diff --git a/src/map/clif.c b/src/map/clif.c
index 855d4c6f0..783a3d399 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -8189,8 +8189,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
mail_clear(sd);
#endif
- quest_pc_login(sd);
-
if(map[sd->bl.m].flag.loadevent) // Lance
npc_script_event(sd, NPCE_LOADMAP);
@@ -12548,39 +12546,28 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd)
}
/*==========================================
- * Questlog System [Kevin]
- * 02B5 <packet_len>.W <ignored>.L { }.10B* <-- UNKOWN PACKET
- * 02B6 <quest_id>.L <state>.B
+ * Questlog System [Kevin] [Inkfish]
*------------------------------------------*/
-
-void clif_parse_questStateAck(int fd, struct map_session_data * sd)
-{
-
-}
-
//Send simple list of quests upon login
//* 02B1 <packet_len>.W <ignored>.L { <quest_id>.L <state>.B }.5B*
void clif_send_questlog(struct map_session_data * sd)
{
int fd = sd->fd;
int i;
+ int len = sd->avail_quests*5+8;
- WFIFOHEAD(fd,sd->num_quests*5+8);
+ WFIFOHEAD(fd,len);
WFIFOW(fd, 0) = 0x02B1;
- WFIFOW(fd, 2) = sd->num_quests*5+8;
+ WFIFOW(fd, 2) = len;
+ WFIFOL(fd, 4) = sd->avail_quests;
- for(i=0; i<MAX_QUEST; i++)
+ for( i = 0; i < sd->avail_quests; i++ )
{
- if(!sd->quest_log[i].quest_id)
- continue;
-
-
WFIFOL(fd, i*5+8) = sd->quest_log[i].quest_id;
WFIFOB(fd, i*5+12) = sd->quest_log[i].state;
-
}
- WFIFOSET(fd, WFIFOW(fd, 2));
+ WFIFOSET(fd, len);
}
@@ -12590,31 +12577,29 @@ void clif_send_questlog_info(struct map_session_data * sd)
{
int fd = sd->fd;
int i, j;
+ int len = sd->avail_quests*104+8;
+ struct mob_db *mob;
- WFIFOHEAD(fd,sd->num_quests*104+8);
+ WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x02B2;
- WFIFOW(fd, 2) = sd->num_quests*104+8;
+ WFIFOW(fd, 2) = len;
+ WFIFOL(fd, 4) = sd->avail_quests;
- for(i=0; i<MAX_QUEST; i++)
+ for( i = 0; i < sd->avail_quests; i++ )
{
- if(!sd->quest_log[i].quest_id)
- continue;
-
WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id;
-
- // I have no idea what the time field does [Kevin]
- WFIFOL(fd, i*104+16) = 0;
+ WFIFOL(fd, i*104+16) = sd->quest_log[i].time;
WFIFOW(fd, i*104+20) = sd->quest_log[i].num_objectives;
- for(j=0; j<sd->quest_log[i].num_objectives; j++)
+ for( j = 0 ; j < sd->quest_log[i].num_objectives; j++ )
{
- WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].objectives[j].count;
- memcpy(WFIFOP(fd, i*104+28+j*30), sd->quest_log[i].objectives[j].name, NAME_LENGTH);
+ WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].count[j];
+ mob = mob_db(sd->quest_log[i].mob[j]);
+ memcpy(WFIFOP(fd, i*104+28+j*30), mob?mob->jname:"NULL", NAME_LENGTH);
}
-
}
- WFIFOSET(fd, WFIFOW(fd, 2));
+ WFIFOSET(fd, len);
}
//Send info when objective info needs an update
@@ -12623,23 +12608,24 @@ void clif_send_quest_info(struct map_session_data * sd, struct quest * qd)
{
int fd = sd->fd;
int i;
+ //int len = MAX_QUEST_OBJECTIVES*30+17;
+ struct mob_db *mob;
- WFIFOHEAD(fd,qd->num_objectives*30+17);
+ WFIFOHEAD(fd, packet_len(0x02B3));
WFIFOW(fd, 0) = 0x02B3;
WFIFOL(fd, 2) = qd->quest_id;
WFIFOB(fd, 6) = qd->state;
-
- //Same time value thing
- WFIFOW(fd, 11) = 0;
+ WFIFOL(fd, 11) = qd->time;
WFIFOW(fd, 15) = qd->num_objectives;
- for(i=0; i<qd->num_objectives; i++)
+ for( i = 0; i < qd->num_objectives; i++ )
{
- WFIFOW(fd, i*30+21) = qd->objectives[i].count;
- memcpy(WFIFOP(fd, i*30+23), qd->objectives[i].name, NAME_LENGTH);
+ WFIFOW(fd, i*30+21) = qd->count[i];
+ mob = mob_db(qd->mob[i]);
+ memcpy(WFIFOP(fd, i*30+23), mob?mob->jname:"NULL", NAME_LENGTH);
}
- WFIFOSET(fd, qd->num_objectives*30+17);
+ WFIFOSET(fd, packet_len(0x02B3));
}
//Send delete msg
@@ -12648,11 +12634,18 @@ void clif_send_quest_delete(struct map_session_data * sd, int quest_id)
{
int fd = sd->fd;
- WFIFOHEAD(fd, 6);
+ WFIFOHEAD(fd, packet_len(0x02B4));
WFIFOW(fd, 0) = 0x02B4;
WFIFOL(fd, 2) = quest_id;
- WFIFOSET(fd, 6);
+ WFIFOSET(fd, packet_len(0x02B4));
+}
+// * 02B5 <packet_len>.W <ignored>.L { }.10B* <-- UNKOWN PACKET
+
+// * 02B6 <quest_id>.L <state>.B
+void clif_parse_questStateAck(int fd, struct map_session_data * sd)
+{
+ quest_update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE);
}
//Change active state of the quest
@@ -12661,11 +12654,11 @@ void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool act
{
int fd = sd->fd;
- WFIFOHEAD(fd, 7);
+ WFIFOHEAD(fd, packet_len(0x02B7));
WFIFOW(fd, 0) = 0x02B7;
WFIFOL(fd, 2) = quest_id;
- WFIFOB(fd, 6) = active?1:0;
- WFIFOSET(fd, 7);
+ WFIFOB(fd, 6) = active;
+ WFIFOSET(fd, packet_len(0x02B7));
}
/*==========================================
@@ -13416,7 +13409,7 @@ static int packetdb_readdb(void)
0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 18, 0, 0, 0, 0, 0,
0, 4, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,117, 6, 0, 7, 7, 0,191, 0, 0, 0, 0, 0, 0,
//#0x02C0
0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 0, 65, 4, 71, 10, 0,
0, 0, 0, 0, 0, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0,
@@ -13632,6 +13625,8 @@ static int packetdb_readdb(void)
{clif_parse_Auction_cancel,"auctioncancel"},
{clif_parse_Auction_close,"auctionclose"},
{clif_parse_Auction_bid,"auctionbid"},
+ // Quest Log System
+ {clif_parse_questStateAck,"queststate"},
#endif
{clif_parse_cashshop_buy,"cashshopbuy"},
{clif_parse_ViewPlayerEquip,"viewplayerequip"},
diff --git a/src/map/clif.h b/src/map/clif.h
index de39ece38..15dda870b 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -431,14 +431,13 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
void clif_viewequip_fail(struct map_session_data* sd);
void clif_equipcheckbox(struct map_session_data* sd);
-//quest system [Kevin]
+//quest system [Kevin] [Inkfish]
void clif_send_questlog(struct map_session_data * sd);
void clif_send_questlog_info(struct map_session_data * sd);
void clif_send_quest_info(struct map_session_data * sd, struct quest * qd);
void clif_send_quest_delete(struct map_session_data * sd, int quest_id);
void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool active);
-
int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type);
int do_final_clif(void);
int do_init_clif(void);
diff --git a/src/map/intif.c b/src/map/intif.c
index e6b5768b4..d077aa881 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -38,7 +38,7 @@ static const int packet_len_table[]={
10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
9, 9,-1,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
-1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus]
- -1,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin]
+ -1,11,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
-1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3870 Mercenaries [Zephyrus]
11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
-1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
@@ -1340,21 +1340,26 @@ int intif_request_questlog(TBL_PC *sd)
int intif_parse_questlog(int fd)
{
-
- int num_quests = (RFIFOB(fd, 2)-8)/sizeof(struct quest);
int char_id = RFIFOL(fd, 4);
int i;
TBL_PC * sd = map_charid2sd(char_id);
//User not online anymore
if(!sd)
- return 0;
+ return -1;
- for(i=0; i<num_quests; i++)
+ sd->avail_quests = sd->num_quests = (RFIFOB(fd, 2)-8)/sizeof(struct quest);
+
+ memset(&sd->quest_log, 0, sizeof(sd->quest_log));
+
+ for( i = 0; i < sd->num_quests; i++ )
{
memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest));
+ if( sd->quest_log[i].state == Q_COMPLETE )
+ sd->avail_quests--;
}
- sd->num_quests = num_quests;
+
+ quest_pc_login(sd);
return 0;
}
@@ -1401,6 +1406,27 @@ int intif_quest_add(int char_id, struct quest * qd)
return 0;
}
+int intif_quest_save(int char_id, struct quest * qd)
+{
+ if(CheckForCharServer())
+ return 0;
+
+ WFIFOHEAD(inter_fd, sizeof(struct quest) + 8);
+ WFIFOW(inter_fd,0) = 0x3063;
+ WFIFOW(inter_fd,2) = sizeof(struct quest) + 8;
+ WFIFOL(inter_fd,4) = char_id;
+ memcpy(WFIFOP(inter_fd,8), qd, sizeof(struct quest));
+ WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
+
+ return 0;
+}
+
+int intif_parse_questSave(int fd)
+{
+ quest_save_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10));
+ return 0;
+}
+
#ifndef TXT_ONLY
/*==========================================
@@ -2038,6 +2064,7 @@ int intif_parse(int fd)
case 0x3860: intif_parse_questlog(fd); break;
case 0x3861: intif_parse_questAdd(fd); break;
case 0x3862: intif_parse_questDelete(fd); break;
+ case 0x3863: intif_parse_questSave(fd); break;
#ifndef TXT_ONLY
// Mail System
diff --git a/src/map/intif.h b/src/map/intif.h
index 38effaaf9..51389bd5b 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -77,6 +77,7 @@ int intif_homunculus_requestdelete(int homun_id);
int intif_request_questlog(struct map_session_data * sd);
int intif_quest_delete(int char_id, int quest_id);
int intif_quest_add(int char_id, struct quest * qd);
+int intif_quest_save(int char_id, struct quest * qd);
// MERCENARY SYSTEM
int intif_mercenary_create(struct s_mercenary *merc);
diff --git a/src/map/map.c b/src/map/map.c
index f5b980506..b1bf03126 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -32,6 +32,7 @@
#include "unit.h"
#include "battle.h"
#include "battleground.h"
+#include "quest.h"
#include "script.h"
#include "mapreg.h"
#include "guild.h"
@@ -4081,6 +4082,7 @@ int do_init(int argc, char *argv[])
do_init_pet();
do_init_merc();
do_init_mercenary();
+ do_init_quest();
do_init_npc();
do_init_unit();
do_init_battleground();
diff --git a/src/map/mob.c b/src/map/mob.c
index e6fa8d2fd..abcb9f469 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -32,6 +32,8 @@
#include "script.h"
#include "atcommand.h"
#include "date.h"
+#include "quest.h"
+
#include <stdio.h>
#include <stdlib.h>
@@ -1992,6 +1994,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
}
pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count);
}
+ if( sd->avail_quests )
+ quest_update_objective(sd, md->class_);
}
// filter out entries not eligible for exp distribution
diff --git a/src/map/pc.h b/src/map/pc.h
index 90e055c17..925db7184 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -377,9 +377,11 @@ struct map_session_data {
bool changed; // if true, should sync with charserver on next mailbox request
} mail;
- //Quest log system [Kevin]
+ //Quest log system [Kevin] [Inkfish]
int num_quests;
- struct quest quest_log[MAX_QUEST];
+ int avail_quests;
+ bool save_quest[MAX_QUEST_DB];
+ struct quest quest_log[MAX_QUEST_DB];
// temporary debug [flaviojs]
const char* debug_file;
diff --git a/src/map/quest.c b/src/map/quest.c
index 057c46d7c..ccde85a07 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -33,46 +33,61 @@
#include <stdarg.h>
#include <time.h>
+#define MAX_QUEST 25
+
//Send quest info on login
int quest_pc_login(TBL_PC * sd)
{
-
if(sd->num_quests == 0)
return 1;
clif_send_questlog(sd);
clif_send_questlog_info(sd);
+
return 0;
}
-int quest_add(TBL_PC * sd, struct quest * qd)
+int quest_add(TBL_PC * sd, int quest_id)
{
- int i;
+ int i, j, count;
- //Search to see if this quest exists
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == qd->quest_id);
+ if( quest_check_quest(sd, quest_id, HAVEQUEST) >= 0 )
+ {
+ ShowError("quest_add: you already have quest %d.\n",quest_id);
+ return -1;
+ }
- //Already have this quest
- if(i!=MAX_QUEST)
- return 1;
+ if( (j = quest_search_db(quest_id)) < 0 )
+ {
+ ShowError("quest_add: quest %d not found in DB.\n",quest_id);
+ return -1;
+ }
- //Find empty quest log spot
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == 0);
+ if( sd->num_quests >= MAX_QUEST_DB || sd->avail_quests >= MAX_QUEST )
+ {
+ ShowError("quest_add: your quest log is full.(max quests: %d, max incompleted quests: %d)\n", MAX_QUEST_DB, MAX_QUEST);
+ return 1;
+ }
- //Quest log is full
- if(i == MAX_QUEST)
- return -1;
+ i = sd->avail_quests;
+ memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
+ memset(&sd->quest_log[i], 0, sizeof(struct quest));
+ sd->quest_log[i].quest_id = quest_db[j].id;
+ if( quest_db[j].time )
+ sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time);
+ sd->quest_log[i].state = Q_ACTIVE;
+ for( count = 0; count < MAX_QUEST_OBJECTIVES && quest_db[j].mob[count]; count++ )
+ sd->quest_log[i].mob[count] = quest_db[j].mob[count];
+ sd->quest_log[i].num_objectives = count;
- //Copy over quest data
- memcpy(&sd->quest_log[i], qd, sizeof(struct quest));
sd->num_quests++;
+ sd->avail_quests++;
//Notify inter server
- intif_quest_add(sd->status.char_id, qd);
+ intif_quest_add(sd->status.char_id, &sd->quest_log[i]);
return 0;
-
}
int quest_add_ack(int char_id, int quest_id, int success)
@@ -83,26 +98,21 @@ int quest_add_ack(int char_id, int quest_id, int success)
///Player no longer on map
if(!sd)
return -1;
+
+ ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id);
+ if( i == sd->avail_quests )
+ return -1; //Shouldn't happen!
- //Search for quest
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
-
- //Quest not found, shouldn't happen?
- if(i == MAX_QUEST)
- return -1;
-
- if(success)
- {
- //Notify client
- clif_send_quest_info(sd, &sd->quest_log[i]);
- }
+ if( success )
+ clif_send_quest_info(sd, &sd->quest_log[i]); //Notify client
else
{
+ sd->avail_quests--;
+ if( sd->num_quests < MAX_QUEST_DB && sd->quest_log[i+1].quest_id )
+ memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i));
+ memset(&sd->quest_log[--sd->num_quests], 0, sizeof(struct quest));
ShowError("Quest %d for character %d could not be added!\n", quest_id, char_id);
-
- //Zero quest
- memset(&sd->quest_log[i], 0, sizeof(struct quest));
- sd->num_quests--;
+ return 1;
}
return 0;
@@ -110,25 +120,20 @@ int quest_add_ack(int char_id, int quest_id, int success)
int quest_delete(TBL_PC * sd, int quest_id)
{
-
- int i;
-
//Search for quest
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
-
- //Quest not found
- if(i == MAX_QUEST)
+ if( quest_check_quest(sd, quest_id, HAVEQUEST) < 0 ) //Quest not found
+ {
+ ShowError("quest_delete: quest %d not found in your quest log.\n",quest_id);
return -1;
+ }
intif_quest_delete(sd->status.char_id, quest_id);
return 0;
-
}
int quest_delete_ack(int char_id, int quest_id, int success)
{
-
int i;
TBL_PC * sd = map_charid2sd(char_id);
@@ -137,65 +142,229 @@ int quest_delete_ack(int char_id, int quest_id, int success)
return -1;
//Search for quest
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
-
- //Quest not found
- if(i == MAX_QUEST)
+ ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
+ if(i == sd->num_quests) //Shouldn't happen!
return -1;
if(success)
{
+ if( sd->quest_log[i].state != Q_COMPLETE )
+ sd->avail_quests--;
+ if( sd->num_quests < MAX_QUEST_DB && sd->quest_log[i+1].quest_id )
+ memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i));
+ memset(&sd->quest_log[--sd->num_quests], 0, sizeof(struct quest));
+ clif_send_quest_delete(sd, quest_id);
+ }
+ else
+ {
+ ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id);
+ return 1;
+ }
- //Zero quest
- memset(&sd->quest_log[i], 0, sizeof(struct quest));
- sd->num_quests--;
+ return 0;
+}
- //Notify client
- clif_send_quest_delete(sd, quest_id);
+void quest_update_objective(TBL_PC * sd, int mob)
+{
+ int i,j;
- return 1;
+ for( i = 0; i < sd->avail_quests; i++ )
+ {
+ if( sd->quest_log[i].state != Q_ACTIVE )
+ continue;
+
+ for( j = 0; j < MAX_QUEST_OBJECTIVES; j++ )
+ if( sd->quest_log[i].mob[j] == mob )
+ {
+ sd->quest_log[i].count[j]++;
+ sd->save_quest[i] = true;
+ //clif_send_quest_info(sd, &sd->quest_log[i]); //TODO: Figure out the real packet [Inkfish]
+ //break;
+ }
+ }
+}
+
+int quest_update_status(TBL_PC * sd, int quest_id, int status)
+{
+ int i;
+ //Search for quest
+ ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id); // Only status of active and inactive quests can't be updated and completed quests can't [Inkfish]
+ if(i == sd->avail_quests) //Quest not found
+ {
+ ShowError("Quest %d not found in your quest log!\n", quest_id);
+ return -1;
+ }
+
+ sd->quest_log[i].state = (quest_state)status;
+ if( status != Q_COMPLETE )
+ {
+ clif_send_quest_status(sd, quest_id, (bool)status);
+ sd->save_quest[i] = true;
}
else
- ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id);
+ {
+ struct quest tmp_quest;
+
+ clif_send_quest_delete(sd, quest_id);
+ sd->avail_quests--;
+
+ memcpy(&tmp_quest, &sd->quest_log[i],sizeof(struct quest));
+ memcpy(&sd->quest_log[i], &sd->quest_log[sd->avail_quests],sizeof(struct quest));
+ memcpy(&sd->quest_log[sd->avail_quests], &tmp_quest,sizeof(struct quest));
+
+ sd->save_quest[sd->avail_quests] = true;
+ }
return 0;
+}
+
+int quest_save(TBL_PC * sd)
+{
+ int i;
+ for( i = 0; i < sd->num_quests; i++ )
+ if( sd->save_quest[i] )
+ intif_quest_save(sd->status.char_id, &sd->quest_log[i]);
+
+ return 0;
}
-int quest_update_objective(TBL_PC * sd, int quest_id, int objective_num, const char * name, int count)
+int quest_save_ack(int char_id, int quest_id, int success)
{
int i;
+ TBL_PC * sd = map_charid2sd(char_id);
- //Search for quest
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
-
- //Quest not found
- if(i == MAX_QUEST)
+ ///Player no longer on map
+ if(!sd)
return -1;
- memcpy(&sd->quest_log[i].objectives[objective_num].name, name, NAME_LENGTH);
- sd->quest_log[i].objectives[objective_num].count = count;
+ //Search for quest
+ ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
+ if(i == sd->num_quests) //Quest not found
+ return -1;
- //Notify client
- clif_send_quest_info(sd, &sd->quest_log[i]);
+ if(success)
+ sd->save_quest[i] = false;
+ else
+ {
+ ShowError("Quest %d for character %d could not be saved!\n", quest_id, char_id);
+ return 1;
+ }
return 0;
}
-bool quest_has_quest(TBL_PC * sd, int quest_id)
+int quest_check_quest(TBL_PC * sd, int quest_id, quest_check_type type)
{
int i;
- ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
+ ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
+ if(i == sd->num_quests)
+ return -1;
+
+ switch( type )
+ {
+ case HAVEQUEST:
+ return sd->quest_log[i].state;
+ case PLAYTIME:
+ return (sd->quest_log[i].time < (unsigned int)time(NULL) ? 2 : sd->quest_log[i].state == Q_COMPLETE ? 1 : 0);
+ case HUNTING:
+ {
+ int j = quest_search_db(quest_id);
+
+ if( j < 0 )
+ {
+ ShowError("quest_check_quest: quest not found in DB\n");
+ return -1;
+ }
+
+ if( sd->quest_log[i].count[0] < quest_db[j].count[0] || sd->quest_log[i].count[1] < quest_db[j].count[1] || sd->quest_log[i].count[2] < quest_db[j].count[2] )
+ {
+ if( sd->quest_log[i].time < (unsigned int)time(NULL) )
+ return 1;
+
+ return 0;
+ }
+
+ return 2;
+ }
+ default:
+ ShowError("quest_check_quest: Unknown parameter %d",type);
+ break;
+ }
- return (i != MAX_QUEST);
+ return -1;
}
-int quest_update_status(TBL_PC * sd, int quest_id, bool status)
+int quest_search_db(int quest_id)
{
+ int i;
+ ARR_FIND(0, MAX_QUEST_DB,i,quest_id == quest_db[i].id);
+ if( i == MAX_QUEST_DB )
+ return -1;
+
+ return i;
+}
+
+int quest_read_db(void)
+{
+ FILE *fp;
+ char line[1024];
+ int j,k = 0;
+ char *str[20],*p,*np;
+
+ sprintf(line, "%s/quest_db.txt", db_path);
+ if( (fp=fopen(line,"r"))==NULL ){
+ ShowError("can't read %s\n", line);
+ return -1;
+ }
+
+ while(fgets(line, sizeof(line), fp))
+ {
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ memset(str,0,sizeof(str));
+
+ for( j = 0, p = line; j < 8;j++ )
+ {
+ if((np=strchr(p,','))!=NULL)
+ {
+ str[j] = p;
+ *np = 0;
+ p = np + 1;
+ }
+ else
+ {
+ ShowError("quest_read_db: insufficient columes in line %s\n", line);
+ continue;
+ }
+ }
+ if(str[0]==NULL)
+ continue;
+
+ memset(&quest_db[k], 0, sizeof(quest_db[0]));
+
+ quest_db[k].id = atoi(str[0]);
+ quest_db[k].time = atoi(str[1]);
+ quest_db[k].mob[0] = atoi(str[2]);
+ quest_db[k].count[0] = atoi(str[3]);
+ quest_db[k].mob[1] = atoi(str[4]);
+ quest_db[k].count[1] = atoi(str[5]);
+ quest_db[k].mob[2] = atoi(str[6]);
+ quest_db[k].count[2] = atoi(str[7]);
+ //memcpy(quest_db[k].name, str[8], sizeof(str[8]));
+ k++;
+ }
+ fclose(fp);
+ ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","quest_db.txt");
return 0;
}
+
+void do_init_quest(void)
+{
+ quest_read_db();
+}
diff --git a/src/map/quest.h b/src/map/quest.h
index c8fa98246..16870d381 100644
--- a/src/map/quest.h
+++ b/src/map/quest.h
@@ -4,19 +4,34 @@
#ifndef _QUEST_H_
#define _QUEST_H_
+typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type;
+
+struct s_quest_db {
+ int id;
+ unsigned int time;
+ int mob[MAX_QUEST_OBJECTIVES];
+ int count[MAX_QUEST_OBJECTIVES];
+ //char name[NAME_LENGTH];
+};
+struct s_quest_db quest_db[MAX_QUEST_DB];
+
int quest_pc_login(TBL_PC * sd);
-int quest_load_info(TBL_PC * sd, struct mmo_charstatus * st);
-int quest_make_savedata(TBL_PC * sd);
-int quest_add(TBL_PC * sd, struct quest * qd);
+int quest_add(TBL_PC * sd, int quest_id);
int quest_add_ack(int char_id, int quest_id, int success);
int quest_delete(TBL_PC * sd, int quest_id);
int quest_delete_ack(int char_id, int quest_id, int success);
-int quest_update_objective(TBL_PC * sd, int quest_id, int objective_num, const char * name, int count);
-int quest_update_status(TBL_PC * sd, int quest_id, bool status);
+void quest_update_objective(TBL_PC * sd, int mob);
+int quest_update_status(TBL_PC * sd, int quest_id, int status);
+int quest_save(TBL_PC * sd);
+int quest_save_ack(int char_id, int quest_id, int success);
+
+int quest_check_quest(TBL_PC * sd, int quest_id, quest_check_type type);
+
+int quest_search_db(int quest_id);
-bool quest_has_quest(TBL_PC * sd, int quest_id);
+void do_init_quest();
#endif
diff --git a/src/map/script.c b/src/map/script.c
index 9edab3e2a..1efd85c6c 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -13426,81 +13426,53 @@ BUILDIN_FUNC(readbook)
Questlog script commands
*******************/
-BUILDIN_FUNC(getquest)
+BUILDIN_FUNC(setquest)
{
-
TBL_PC * sd = script_rid2sd(st);
- struct quest qd;
- int i, count = 0;
- char * temp;
-
- memset(&qd, 0, sizeof(struct quest));
-
- qd.quest_id = script_getnum(st, 2);
- qd.time = script_getnum(st, 3);
- qd.state = Q_ACTIVE;
-
- for(i=0; i<(script_lastdata(st)-3) && (i/2) < MAX_QUEST_OBJECTIVES; i+=2)
- {
- temp = (char*)script_getstr(st, i+4);
- memcpy(&qd.objectives[i/2].name, temp, NAME_LENGTH);
- temp = NULL;
- qd.objectives[i/2].count = script_getnum(st, i+5);
- count++;
- }
-
- qd.num_objectives = count;
-
- quest_add(sd, &qd);
+ quest_add(sd, script_getnum(st, 2));
return 0;
-
}
-BUILDIN_FUNC(deletequest)
+BUILDIN_FUNC(erasequest)
{
-
TBL_PC * sd = script_rid2sd(st);
- int qid = script_getnum(st, 2);
- quest_delete(sd, qid);
+ quest_delete(sd, script_getnum(st, 2));
return 0;
-
}
-BUILDIN_FUNC(setquestobjective)
+BUILDIN_FUNC(completequest)
{
-
TBL_PC * sd = script_rid2sd(st);
- int qid = script_getnum(st, 2);
- int num = script_getnum(st, 3);
- const char * str = script_getstr(st, 4);
- int count = script_getnum(st, 5);
-
- quest_update_objective(sd, qid, num, str, count);
+ quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE);
return 0;
}
-BUILDIN_FUNC(hasquest)
+BUILDIN_FUNC(changequest)
{
-
TBL_PC * sd = script_rid2sd(st);
- int qid = script_getnum(st, 2);
+ int q1 = script_getnum(st, 2), q2 = script_getnum(st, 3);
- script_pushint(st, quest_has_quest(sd, qid)?1:0);
+ if( quest_check_quest(sd, q1, HAVEQUEST) == Q_ACTIVE && quest_add(sd, q2) >= 0 )
+ {
+ quest_update_status(sd, q1, Q_COMPLETE);
+ intif_quest_save(sd->status.char_id, &sd->quest_log[sd->avail_quests]);
+ }
return 0;
}
-BUILDIN_FUNC(setqueststatus)
+BUILDIN_FUNC(checkquest)
{
-
TBL_PC * sd = script_rid2sd(st);
- int qid = script_getnum(st, 2);
- bool active = script_getnum(st, 3)?true:false;
+ quest_check_type type = HAVEQUEST;
+
+ if( script_hasdata(st, 3) )
+ type = (quest_check_type)script_getnum(st, 3);
- quest_update_status(sd, qid, active);
+ script_pushint(st, quest_check_quest(sd, script_getnum(st, 2), type));
return 0;
}
@@ -14472,11 +14444,6 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(openauction,""),
BUILDIN_DEF(checkcell,"siii"),
BUILDIN_DEF(setcell,"siiiiii"),
- BUILDIN_DEF(getquest, "ii*"),
- BUILDIN_DEF(deletequest, "i"),
- BUILDIN_DEF(setquestobjective, "iisi"),
- BUILDIN_DEF(setqueststatus, "ii"),
- BUILDIN_DEF(hasquest, "i"),
BUILDIN_DEF(setwall,"siiiiis"),
BUILDIN_DEF(delwall,"s"),
BUILDIN_DEF(mercenary_create,"ii"),
@@ -14519,5 +14486,11 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(instance_id,"?"),
BUILDIN_DEF(instance_warpall,"sii"),
BUILDIN_DEF(instance_set_timeout,"ii?"),
+ //Quest Log System [Inkfish]
+ BUILDIN_DEF(setquest, "i"),
+ BUILDIN_DEF(erasequest, "i"),
+ BUILDIN_DEF(completequest, "i"),
+ BUILDIN_DEF(checkquest, "i*"),
+ BUILDIN_DEF(changequest, "ii"),
{NULL,NULL,NULL},
};