summaryrefslogtreecommitdiff
path: root/src/char/int_pet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/char/int_pet.c')
-rw-r--r--src/char/int_pet.c232
1 files changed, 152 insertions, 80 deletions
diff --git a/src/char/int_pet.c b/src/char/int_pet.c
index 880de668d..8b42bac1d 100644
--- a/src/char/int_pet.c
+++ b/src/char/int_pet.c
@@ -43,97 +43,162 @@ struct inter_pet_interface *inter_pet;
/**
* Saves a pet to the SQL database.
*
- * @remark
- * In case of newly created pet, the pet ID is not updated to reflect the
- * newly assigned ID. The caller must do so.
+ * Table structure:
+ * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`)
+ *
+ * @remark In case of newly created pet, the pet ID is not updated to reflect the newly assigned ID. The caller must do so.
*
* @param p The pet data to save.
- * @return The ID of the saved pet.
- * @retval 0 in case of errors.
- */
+ * @return The ID of the saved pet, or 0 in case of errors.
+ *
+ **/
static int inter_pet_tosql(const struct s_pet *p)
{
- //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`)
- char esc_name[NAME_LENGTH*2+1];// escaped pet name
- int pet_id = 0, hungry = 0, intimate = 0;
-
nullpo_ret(p);
- SQL->EscapeStringLen(inter->sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
- hungry = cap_value(p->hungry, 0, 100);
- intimate = cap_value(p->intimate, 0, 1000);
-
- if (p->pet_id == 0) {
- // New pet.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` "
- "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) "
- "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed)) {
- Sql_ShowDebug(inter->sql_handle);
+ struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return 0;
+ }
+
+ int pet_id = 0;
+
+ if (p->pet_id == 0) { // New pet.
+ const char *query = "INSERT INTO `%s` "
+ "(`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, "
+ "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
return 0;
}
+
pet_id = (int)SQL->LastInsertId(inter->sql_handle);
- } else {
- // Update pet.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d', `autofeed`='%d' WHERE `pet_id`='%d'",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed, p->pet_id)) {
- Sql_ShowDebug(inter->sql_handle);
+ } else { // Update pet.
+ const char *query = "UPDATE `%s` SET "
+ "`class`=?, `name`=?, `account_id`=?, `char_id`=?, `level`=?, `egg_id`=?, `equip`=?, "
+ "`intimate`=?, `hungry`=?, `rename_flag`=?, `incubate`=?, `autofeed`=? "
+ "WHERE `pet_id`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 12, SQLDT_INT32, &p->pet_id, sizeof(p->pet_id)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
return 0;
}
+
pet_id = p->pet_id;
}
+ SQL->StmtFree(stmt);
+
if (chr->show_save_log)
ShowInfo("Pet saved %d - %s.\n", pet_id, p->name);
return pet_id;
}
+/**
+ * Loads a pet's data from the SQL database.
+ *
+ * Table structure:
+ * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`)
+ *
+ * @param pet_id The pet's ID.
+ * @param p The pet data to save the SQL data in.
+ * @return Always 0.
+ *
+ **/
static int inter_pet_fromsql(int pet_id, struct s_pet *p)
{
- char* data;
- size_t len;
+ nullpo_ret(p);
+
+ struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return 0;
+ }
#ifdef NOISY
ShowInfo("Loading pet (%d)...\n",pet_id);
#endif
- nullpo_ret(p);
+
memset(p, 0, sizeof(struct s_pet));
- //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`)
+ const char *query = "SELECT "
+ "`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, "
+ "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed` "
+ "FROM `%s` WHERE `pet_id`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &pet_id, sizeof(pet_id)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_STRING, &p->name, sizeof(p->name), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed), NULL, NULL)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
+ }
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`,`autofeed` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
- {
- Sql_ShowDebug(inter->sql_handle);
+ if (SQL->StmtNumRows(stmt) < 1) {
+ ShowError("inter_pet_fromsql: Requested non-existant pet ID: %d\n", pet_id);
+ SQL->StmtFree(stmt);
return 0;
}
- if( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) )
- {
- p->pet_id = pet_id;
- SQL->GetData(inter->sql_handle, 1, &data, NULL); p->class_ = atoi(data);
- SQL->GetData(inter->sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH));
- SQL->GetData(inter->sql_handle, 3, &data, NULL); p->account_id = atoi(data);
- SQL->GetData(inter->sql_handle, 4, &data, NULL); p->char_id = atoi(data);
- SQL->GetData(inter->sql_handle, 5, &data, NULL); p->level = atoi(data);
- SQL->GetData(inter->sql_handle, 6, &data, NULL); p->egg_id = atoi(data);
- SQL->GetData(inter->sql_handle, 7, &data, NULL); p->equip = atoi(data);
- SQL->GetData(inter->sql_handle, 8, &data, NULL); p->intimate = atoi(data);
- SQL->GetData(inter->sql_handle, 9, &data, NULL); p->hungry = atoi(data);
- SQL->GetData(inter->sql_handle, 10, &data, NULL); p->rename_flag = atoi(data);
- SQL->GetData(inter->sql_handle, 11, &data, NULL); p->incubate = atoi(data);
- SQL->GetData(inter->sql_handle, 12, &data, NULL); p->autofeed = atoi(data);
-
- SQL->FreeResult(inter->sql_handle);
-
- p->hungry = cap_value(p->hungry, 0, 100);
- p->intimate = cap_value(p->intimate, 0, 1000);
-
- if (chr->show_save_log)
- ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name);
+ if (SQL_ERROR == SQL->StmtNextRow(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
}
+
+ SQL->StmtFree(stmt);
+ p->pet_id = pet_id;
+
+ if (chr->show_save_log)
+ ShowInfo("Pet loaded %d - %s.\n", pet_id, p->name);
+
return 0;
}
//----------------------------------------------
@@ -160,41 +225,48 @@ static int inter_pet_delete(int pet_id)
return 0;
}
//------------------------------------------------------
+
+/**
+ * Creates a new pet and inserts its data into the `pet` SQL table.
+ *
+ * @param account_id The pet's master's account ID.
+ * @param char_id The pet's master's char ID.
+ * @param pet_class The pet's class/monster ID.
+ * @param pet_lv The pet's level.
+ * @param pet_egg_id The pet's egg's item ID.
+ * @param pet_equip The pet's equipment's item ID.
+ * @param intimate The pet's intimacy value.
+ * @param hungry The pet's hunger value.
+ * @param rename_flag The pet's rename flag.
+ * @param incubate The pet's incubate state.
+ * @param pet_name The pet's name.
+ * @return The created pet's data struct, or NULL in case of errors.
+ *
+ **/
static struct s_pet *inter_pet_create(int account_id, int char_id, int pet_class, int pet_lv, int pet_egg_id,
- int pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name)
+ int pet_equip, short intimate, short hungry, char rename_flag,
+ char incubate, const char *pet_name)
{
- nullpo_ret(pet_name);
+ nullpo_retr(NULL, pet_name);
+
memset(inter_pet->pt, 0, sizeof(struct s_pet));
safestrncpy(inter_pet->pt->name, pet_name, NAME_LENGTH);
- if(incubate == 1)
- inter_pet->pt->account_id = inter_pet->pt->char_id = 0;
- else {
- inter_pet->pt->account_id = account_id;
- inter_pet->pt->char_id = char_id;
- }
+ inter_pet->pt->account_id = (incubate == 1) ? 0 : account_id;
+ inter_pet->pt->char_id = (incubate == 1) ? 0 : char_id;
inter_pet->pt->class_ = pet_class;
inter_pet->pt->level = pet_lv;
inter_pet->pt->egg_id = pet_egg_id;
inter_pet->pt->equip = pet_equip;
- inter_pet->pt->intimate = intimate;
- inter_pet->pt->hungry = hungry;
+ inter_pet->pt->intimate = cap_value(intimate, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+ inter_pet->pt->hungry = cap_value(hungry, PET_HUNGER_STARVING, PET_HUNGER_STUFFED);
inter_pet->pt->rename_flag = rename_flag;
inter_pet->pt->incubate = incubate;
+ inter_pet->pt->pet_id = 0; // Signal NEW pet.
- if(inter_pet->pt->hungry < 0)
- inter_pet->pt->hungry = 0;
- else if(inter_pet->pt->hungry > 100)
- inter_pet->pt->hungry = 100;
- if(inter_pet->pt->intimate < 0)
- inter_pet->pt->intimate = 0;
- else if(inter_pet->pt->intimate > 1000)
- inter_pet->pt->intimate = 1000;
-
- inter_pet->pt->pet_id = 0; //Signal NEW pet.
if ((inter_pet->pt->pet_id = inter_pet->tosql(inter_pet->pt)) != 0)
return inter_pet->pt;
- else //Failed...
- return NULL;
+
+ return NULL;
}
static struct s_pet *inter_pet_load(int account_id, int char_id, int pet_id)