Made view_data for mob unit changes persistent (#2316)
Made view_data for mobs changes persistent Fixes #2269 Thanks to @Yuchinin --- Fixed reloadmobdb breaking the view ids Fixes #2326 Thanks to @karlseven --- Allowed updating mob's class to a pc class Fixed sex change so that the client is automatically refreshed Respawn the monster on clientside if the class is changed Thanks to @Jeybla and @aleos89 for helping!
This commit is contained in:
parent
9c6a89076d
commit
abfd1980de
@ -336,9 +336,49 @@ int mobdb_checkid(const int id)
|
|||||||
struct view_data * mob_get_viewdata(int mob_id)
|
struct view_data * mob_get_viewdata(int mob_id)
|
||||||
{
|
{
|
||||||
if (mob_db(mob_id) == mob_dummy)
|
if (mob_db(mob_id) == mob_dummy)
|
||||||
return 0;
|
return NULL;
|
||||||
return &mob_db(mob_id)->vd;
|
return &mob_db(mob_id)->vd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create unique view data associated to a spawned monster.
|
||||||
|
* @param md: Mob to adjust
|
||||||
|
*/
|
||||||
|
void mob_set_dynamic_viewdata( struct mob_data* md ){
|
||||||
|
// If it is a valid monster and it has not already been created
|
||||||
|
if( md && !md->vd_changed ){
|
||||||
|
// Allocate a dynamic entry
|
||||||
|
struct view_data* vd = (struct view_data*)aMalloc( sizeof( struct view_data ) );
|
||||||
|
|
||||||
|
// Copy the current values
|
||||||
|
memcpy( vd, md->vd, sizeof( struct view_data ) );
|
||||||
|
|
||||||
|
// Update the pointer to the new entry
|
||||||
|
md->vd = vd;
|
||||||
|
|
||||||
|
// Flag it as changed so it is freed later on
|
||||||
|
md->vd_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free any view data associated to a spawned monster.
|
||||||
|
* @param md: Mob to free
|
||||||
|
*/
|
||||||
|
void mob_free_dynamic_viewdata( struct mob_data* md ){
|
||||||
|
// If it is a valid monster and it has already been allocated
|
||||||
|
if( md && md->vd_changed ){
|
||||||
|
// Free it
|
||||||
|
aFree( md->vd );
|
||||||
|
|
||||||
|
// Remove the reference
|
||||||
|
md->vd = NULL;
|
||||||
|
|
||||||
|
// Unflag it as changed
|
||||||
|
md->vd_changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* Cleans up mob-spawn data to make it "valid"
|
* Cleans up mob-spawn data to make it "valid"
|
||||||
*------------------------------------------*/
|
*------------------------------------------*/
|
||||||
@ -5189,6 +5229,9 @@ static void mob_load(void)
|
|||||||
mob_skill_db_set();
|
mob_skill_db_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize monster data
|
||||||
|
*/
|
||||||
void mob_db_load(void){
|
void mob_db_load(void){
|
||||||
memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
|
memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
|
||||||
mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
|
mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
|
||||||
@ -5201,11 +5244,42 @@ void mob_db_load(void){
|
|||||||
mob_load();
|
mob_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the proper view data on monsters during mob_db reload.
|
||||||
|
* @param md: Mob to adjust
|
||||||
|
* @param args: va_list of arguments
|
||||||
|
* @return 0
|
||||||
|
*/
|
||||||
|
static int mob_reload_sub( struct mob_data *md, va_list args ){
|
||||||
|
if( md->bl.prev == NULL ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the view data was not overwritten manually
|
||||||
|
if( !md->vd_changed ){
|
||||||
|
// Get the new view data from the mob database
|
||||||
|
md->vd = mob_get_viewdata(md->mob_id);
|
||||||
|
|
||||||
|
// Respawn all mobs on client side so that they are displayed correctly(if their view id changed)
|
||||||
|
clif_clearunit_area(&md->bl, CLR_OUTSIGHT);
|
||||||
|
clif_spawn(&md->bl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload monster data
|
||||||
|
*/
|
||||||
void mob_reload(void) {
|
void mob_reload(void) {
|
||||||
do_final_mob();
|
do_final_mob();
|
||||||
mob_db_load();
|
mob_db_load();
|
||||||
|
map_foreachmob(mob_reload_sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear spawn data for all monsters
|
||||||
|
*/
|
||||||
void mob_clear_spawninfo()
|
void mob_clear_spawninfo()
|
||||||
{ //Clears spawn related information for a script reload.
|
{ //Clears spawn related information for a script reload.
|
||||||
int i;
|
int i;
|
||||||
|
@ -173,6 +173,7 @@ struct mob_data {
|
|||||||
struct block_list bl;
|
struct block_list bl;
|
||||||
struct unit_data ud;
|
struct unit_data ud;
|
||||||
struct view_data *vd;
|
struct view_data *vd;
|
||||||
|
bool vd_changed;
|
||||||
struct status_data status, *base_status; //Second one is in case of leveling up mobs, or tiny/large mobs.
|
struct status_data status, *base_status; //Second one is in case of leveling up mobs, or tiny/large mobs.
|
||||||
struct status_change sc;
|
struct status_change sc;
|
||||||
struct mob_db *db; //For quick data access (saves doing mob_db(md->mob_id) all the time) [Skotlex]
|
struct mob_db *db; //For quick data access (saves doing mob_db(md->mob_id) all the time) [Skotlex]
|
||||||
@ -298,6 +299,8 @@ int mobdb_searchname(const char *str);
|
|||||||
int mobdb_searchname_array(struct mob_db** data, int size, const char *str);
|
int mobdb_searchname_array(struct mob_db** data, int size, const char *str);
|
||||||
int mobdb_checkid(const int id);
|
int mobdb_checkid(const int id);
|
||||||
struct view_data* mob_get_viewdata(int mob_id);
|
struct view_data* mob_get_viewdata(int mob_id);
|
||||||
|
void mob_set_dynamic_viewdata( struct mob_data* md );
|
||||||
|
void mob_free_dynamic_viewdata( struct mob_data* md );
|
||||||
|
|
||||||
struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int mob_id, const char *event, unsigned int size, unsigned int ai);
|
struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int mob_id, const char *event, unsigned int size, unsigned int ai);
|
||||||
|
|
||||||
|
@ -17769,6 +17769,23 @@ BUILDIN_FUNC(setunitdata)
|
|||||||
md->base_status = (struct status_data*)aCalloc(1, sizeof(struct status_data));
|
md->base_status = (struct status_data*)aCalloc(1, sizeof(struct status_data));
|
||||||
memcpy(md->base_status, &md->db->status, sizeof(struct status_data));
|
memcpy(md->base_status, &md->db->status, sizeof(struct status_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the view data will be modified
|
||||||
|
switch( type ){
|
||||||
|
case UMOB_SEX:
|
||||||
|
//case UMOB_CLASS: // Called by status_set_viewdata
|
||||||
|
case UMOB_HAIRSTYLE:
|
||||||
|
case UMOB_HAIRCOLOR:
|
||||||
|
case UMOB_HEADBOTTOM:
|
||||||
|
case UMOB_HEADMIDDLE:
|
||||||
|
case UMOB_HEADTOP:
|
||||||
|
case UMOB_CLOTHCOLOR:
|
||||||
|
case UMOB_SHIELD:
|
||||||
|
case UMOB_WEAPON:
|
||||||
|
mob_set_dynamic_viewdata( md );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case UMOB_SIZE: md->base_status->size = (unsigned char)value; calc_status = true; break;
|
case UMOB_SIZE: md->base_status->size = (unsigned char)value; calc_status = true; break;
|
||||||
case UMOB_LEVEL: md->level = (unsigned short)value; break;
|
case UMOB_LEVEL: md->level = (unsigned short)value; break;
|
||||||
@ -17782,8 +17799,8 @@ BUILDIN_FUNC(setunitdata)
|
|||||||
case UMOB_MODE: md->base_status->mode = (enum e_mode)value; calc_status = true; break;
|
case UMOB_MODE: md->base_status->mode = (enum e_mode)value; calc_status = true; break;
|
||||||
case UMOB_AI: md->special_state.ai = (enum mob_ai)value; break;
|
case UMOB_AI: md->special_state.ai = (enum mob_ai)value; break;
|
||||||
case UMOB_SCOPTION: md->sc.option = (unsigned short)value; break;
|
case UMOB_SCOPTION: md->sc.option = (unsigned short)value; break;
|
||||||
case UMOB_SEX: md->vd->sex = (char)value; break;
|
case UMOB_SEX: md->vd->sex = (char)value; clif_clearunit_area(bl, CLR_OUTSIGHT); clif_spawn(bl); break;
|
||||||
case UMOB_CLASS: status_set_viewdata(bl, (unsigned short)value); break;
|
case UMOB_CLASS: status_set_viewdata(bl, (unsigned short)value); clif_clearunit_area(bl, CLR_OUTSIGHT); clif_spawn(bl); break;
|
||||||
case UMOB_HAIRSTYLE: clif_changelook(bl, LOOK_HAIR, (unsigned short)value); break;
|
case UMOB_HAIRSTYLE: clif_changelook(bl, LOOK_HAIR, (unsigned short)value); break;
|
||||||
case UMOB_HAIRCOLOR: clif_changelook(bl, LOOK_HAIR_COLOR, (unsigned short)value); break;
|
case UMOB_HAIRCOLOR: clif_changelook(bl, LOOK_HAIR_COLOR, (unsigned short)value); break;
|
||||||
case UMOB_HEADBOTTOM: clif_changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short)value); break;
|
case UMOB_HEADBOTTOM: clif_changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short)value); break;
|
||||||
|
@ -7680,9 +7680,15 @@ void status_set_viewdata(struct block_list *bl, int class_)
|
|||||||
case BL_MOB:
|
case BL_MOB:
|
||||||
{
|
{
|
||||||
TBL_MOB* md = (TBL_MOB*)bl;
|
TBL_MOB* md = (TBL_MOB*)bl;
|
||||||
if (vd)
|
if (vd){
|
||||||
|
mob_free_dynamic_viewdata( md );
|
||||||
|
|
||||||
md->vd = vd;
|
md->vd = vd;
|
||||||
else
|
}else if( pcdb_checkid( class_ ) ){
|
||||||
|
mob_set_dynamic_viewdata( md );
|
||||||
|
|
||||||
|
md->vd->class_ = class_;
|
||||||
|
}else
|
||||||
ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_);
|
ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3305,6 +3305,8 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
|||||||
case BL_MOB: {
|
case BL_MOB: {
|
||||||
struct mob_data *md = (struct mob_data*)bl;
|
struct mob_data *md = (struct mob_data*)bl;
|
||||||
|
|
||||||
|
mob_free_dynamic_viewdata( md );
|
||||||
|
|
||||||
if( md->spawn_timer != INVALID_TIMER ) {
|
if( md->spawn_timer != INVALID_TIMER ) {
|
||||||
delete_timer(md->spawn_timer,mob_delayspawn);
|
delete_timer(md->spawn_timer,mob_delayspawn);
|
||||||
md->spawn_timer = INVALID_TIMER;
|
md->spawn_timer = INVALID_TIMER;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user