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)
|
||||
{
|
||||
if (mob_db(mob_id) == mob_dummy)
|
||||
return 0;
|
||||
return NULL;
|
||||
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"
|
||||
*------------------------------------------*/
|
||||
@ -5189,6 +5229,9 @@ static void mob_load(void)
|
||||
mob_skill_db_set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize monster data
|
||||
*/
|
||||
void mob_db_load(void){
|
||||
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
|
||||
@ -5201,11 +5244,42 @@ void mob_db_load(void){
|
||||
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) {
|
||||
do_final_mob();
|
||||
mob_db_load();
|
||||
map_foreachmob(mob_reload_sub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear spawn data for all monsters
|
||||
*/
|
||||
void mob_clear_spawninfo()
|
||||
{ //Clears spawn related information for a script reload.
|
||||
int i;
|
||||
|
@ -173,6 +173,7 @@ struct mob_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud;
|
||||
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_change sc;
|
||||
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_checkid(const int 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);
|
||||
|
||||
|
@ -17769,6 +17769,23 @@ BUILDIN_FUNC(setunitdata)
|
||||
md->base_status = (struct status_data*)aCalloc(1, 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) {
|
||||
case UMOB_SIZE: md->base_status->size = (unsigned char)value; calc_status = true; 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_AI: md->special_state.ai = (enum mob_ai)value; break;
|
||||
case UMOB_SCOPTION: md->sc.option = (unsigned short)value; break;
|
||||
case UMOB_SEX: md->vd->sex = (char)value; break;
|
||||
case UMOB_CLASS: status_set_viewdata(bl, (unsigned short)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); clif_clearunit_area(bl, CLR_OUTSIGHT); clif_spawn(bl); 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_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:
|
||||
{
|
||||
TBL_MOB* md = (TBL_MOB*)bl;
|
||||
if (vd)
|
||||
if (vd){
|
||||
mob_free_dynamic_viewdata( md );
|
||||
|
||||
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_);
|
||||
}
|
||||
break;
|
||||
|
@ -3305,6 +3305,8 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
case BL_MOB: {
|
||||
struct mob_data *md = (struct mob_data*)bl;
|
||||
|
||||
mob_free_dynamic_viewdata( md );
|
||||
|
||||
if( md->spawn_timer != INVALID_TIMER ) {
|
||||
delete_timer(md->spawn_timer,mob_delayspawn);
|
||||
md->spawn_timer = INVALID_TIMER;
|
||||
|
Loading…
x
Reference in New Issue
Block a user