Jump to content

  •  

Nardoth

Member Since 25 May 2015
Offline Last Active Oct 12 2016 08:10 AM
-----

Topics I've Started

Consumables with itemskill not working

17 September 2016 - 01:02 AM

For some reason, when I try to use a magnifier, flywing, Yggdrasil leaf and other items like them, they would be consumed and no skill will happen.

 

There are no errors when loading the server nor when using the items. I updated my hercules like 2 weeks ago but I don't remember if I had this problem before, didn't check.

 

Also I never edited the itemskill script command nor the functions it uses as far as I can recall.

 

wat do?

 

 

UPDATE: I checked my previous version of hercules that was like a year old and the bug is still there.
PACKETVER is 20140205.

 

UPDATE 2: Used an unmodified version, bug was gone. Must be something I made, no idea what could be causing it since I didn't messed up with that :/

 

LAST UPDATE: Found the problem, was calling skill->check_condition_castbegin at clif_parse_UseSkillToId and ToPos too.


Walk over NPC and Bank questions

14 September 2016 - 05:08 PM

Hi, is there a way to make an invisible npc such that you can walk over it instead of pushing you to a free cell? It seems like FAKE_NPC pushes you away.

 

Also is there a way to open the bank in a script the same way you open the auction with the command "openauction" ?

 

EDIT: Already solved it, someone close this.


Getting a melee or ground targeted skill and target

25 August 2016 - 01:31 AM

When a magic skill is casted on an enemy of my map_session_data *sd I can get both the skill id and target with sd->ud.skill_id and sd->ud.skill_target but this is not the case on a melee or ground targeted skill (it returns 0 with that method, for some reason).

 

How do I get both of those variables in those cases?

 

EDIT: Close this thread, I solved it.


Clone AI

21 August 2016 - 06:01 PM

Hi, is there a way to make a clone mimic the player in basic attacks, skills and targets?
 

Apparently, changing the parameters of my mobdata *MyClone like MyClone->ud.target = sd->ud.target; and a lot more of variables like that are not helping: as soon as I attack something, the clone starts attacking and using random skills on the target indefenitely.

 

Some help and documentation would be really appreciated. I would also need for the mob to be able to copy Guild and Party names and graphical auras and effects, but I'm not sure if it would be possible.

 

The code I use as a base is the mob_clone_spawn at mob.c but for the lazy I'll leave it here
 

int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration) {
	int class_;
	int i,j,h,inf, fd;
	struct mob_data *md;
	struct mob_skill *ms;
	struct mob_db* db;
	struct status_data *mstatus;

	nullpo_ret(sd);

	if(pc_isdead(sd) && master_id && flag&1)
		return 0;

	ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL );
	if(class_ >= MOB_CLONE_END)
		return 0;

	db = mob->db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
	mstatus = &db->status;
	strcpy(db->sprite,sd->status.name);
	strcpy(db->name,sd->status.name);
	strcpy(db->jname,sd->status.name);
	db->lv=status->get_lv(&sd->bl);
	memcpy(mstatus, &sd->base_status, sizeof(struct status_data));
	mstatus->rhw.atk2= mstatus->dex + mstatus->rhw.atk + mstatus->rhw.atk2; //Max ATK
	mstatus->rhw.atk = mstatus->dex; //Min ATK
	if (mstatus->lhw.atk) {
		mstatus->lhw.atk2= mstatus->dex + mstatus->lhw.atk + mstatus->lhw.atk2; //Max ATK
		mstatus->lhw.atk = mstatus->dex; //Min ATK
	}
	if (mode) //User provided mode.
		mstatus->mode = mode;
	else if (flag&1) //Friendly Character, remove looting.
		mstatus->mode &= ~MD_LOOTER;
	mstatus->hp = mstatus->max_hp;
	mstatus->sp = mstatus->max_sp;
	memcpy(&db->vd, &sd->vd, sizeof(struct view_data));
	db->base_exp=1;
	db->job_exp=1;
	db->range2=AREA_SIZE; //Let them have the same view-range as players.
	db->range3=AREA_SIZE; //Min chase of a screen.
	db->option=sd->sc.option;

	//Skill copy [Skotlex]
	ms = &db->skill[0];

	/**
	 * We temporarily disable sd's fd so it doesn't receive the messages from skill_check_condition_castbegin
	 **/
	fd = sd->fd;
	sd->fd = 0;

	//Go Backwards to give better priority to advanced skills.
	for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
		int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][j].idx;
		int skill_id = pc->skill_tree[pc->class2idx(sd->status.class_)][j].id;
		if (!skill_id || sd->status.skill[idx].lv < 1 ||
			(skill->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
		)
			continue;
		for(h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) {
			if( skill_id == map->list[sd->bl.m].zone->disabled_skills[h]->nameid && map->list[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE ) {
				break;
			}
		}
		if( h < map->list[sd->bl.m].zone->disabled_skills_count )
			continue;
		//Normal aggressive mob, disable skills that cannot help them fight
		//against players (those with flags UF_NOMOB and UF_NOPC are specific
		//to always aid players!) [Skotlex]
		if (!(flag&1) &&
			skill->get_unit_id(skill_id, 0) &&
			skill->get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC))
			continue;
		/**
		 * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
		 **/
		if( !skill->check_condition_castbegin(sd,skill_id,sd->status.skill[idx].lv) )
			continue;

		memset (&ms[i], 0, sizeof(struct mob_skill));
		ms[i].skill_id = skill_id;
		ms[i].skill_lv = sd->status.skill[idx].lv;
		ms[i].state = MSS_ANY;
		ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5%
		ms[i].emotion = -1;
		ms[i].cancel = 0;
		ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv);
		ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv);

		inf = skill->db[idx].inf;
		if (inf&INF_ATTACK_SKILL) {
			ms[i].target = MST_TARGET;
			ms[i].cond1 = MSC_ALWAYS;
			if (skill->get_range(skill_id, ms[i].skill_lv)  > 3)
				ms[i].state = MSS_ANYTARGET;
			else
				ms[i].state = MSS_BERSERK;
		} else if(inf&INF_GROUND_SKILL) {
			if (skill->get_inf2(skill_id)&INF2_TRAP) { //Traps!
				ms[i].state = MSS_IDLE;
				ms[i].target = MST_AROUND2;
				ms[i].delay = 60000;
			} else if (skill->get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy
				ms[i].state = MSS_ANYTARGET;
				ms[i].target = MST_TARGET;
				ms[i].cond1 = MSC_ALWAYS;
			} else { //Target allies
				ms[i].target = MST_FRIEND;
				ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
				ms[i].cond2 = 95;
			}
		} else if (inf&INF_SELF_SKILL) {
			if (skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill.
				ms[i].target = MST_TARGET;
				ms[i].cond1 = MSC_ALWAYS;
				if (skill->get_range(skill_id, ms[i].skill_lv)  > 3) {
					ms[i].state = MSS_ANYTARGET;
				} else {
					ms[i].state = MSS_BERSERK;
				}
			} else { //Self skill
				ms[i].target = MST_SELF;
				ms[i].cond1 = MSC_MYHPLTMAXRATE;
				ms[i].cond2 = 90;
				ms[i].permillage = 2000;
				//Delay: Remove the stock 5 secs and add half of the support time.
				ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2;
				if (ms[i].delay < 5000)
					ms[i].delay = 5000; //With a minimum of 5 secs.
			}
		} else if (inf&INF_SUPPORT_SKILL) {
			ms[i].target = MST_FRIEND;
			ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
			ms[i].cond2 = 90;
			if (skill_id == AL_HEAL)
				ms[i].permillage = 5000; //Higher skill rate usage for heal.
			else if (skill_id == ALL_RESURRECTION)
				ms[i].cond2 = 1;
			//Delay: Remove the stock 5 secs and add half of the support time.
			ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2;
			if (ms[i].delay < 2000)
				ms[i].delay = 2000; //With a minimum of 2 secs.

			if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self.
				memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill));
				db->maxskill = ++i;
				ms[i].target = MST_SELF;
				ms[i].cond1 = MSC_MYHPLTMAXRATE;
			}
		} else {
			switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered.
				case MO_TRIPLEATTACK:
				case TF_DOUBLE:
				case GS_CHAINACTION:
					ms[i].state = MSS_BERSERK;
					ms[i].target = MST_TARGET;
					ms[i].cond1 = MSC_ALWAYS;
					ms[i].permillage = skill_id==MO_TRIPLEATTACK?(3000-ms[i].skill_lv*100):(ms[i].skill_lv*500);
					ms[i].delay -= 5000; //Remove the added delay as these could trigger on "all hits".
					break;
				default: //Untreated Skill
					continue;
			}
		}
		if (battle_config.mob_skill_rate!= 100)
			ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100;
		if (battle_config.mob_skill_delay != 100)
			ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100;

		db->maxskill = ++i;
	}

	/**
	 * We grant the session it's fd value back.
	 **/
	sd->fd = fd;

	//Finally, spawn it.
	md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE);
	if (!md) return 0; //Failed?

	md->special_state.clone = 1;

	if (master_id || flag || duration) { //Further manipulate crafted char.
		if (flag&1) //Friendly Character
			md->special_state.ai = AI_ATTACK;
		if (master_id) //Attach to Master
			md->master_id = master_id;
		if (duration) //Auto Delete after a while.
		{
			if( md->deletetimer != INVALID_TIMER )
				timer->delete(md->deletetimer, mob->timer_delete);
			md->deletetimer = timer->add(timer->gettick() + duration, mob->timer_delete, md->bl.id, 0);
		}
	}

	mob->spawn(md);

	return md->bl.id;
}

EDIT: Someone close this, already solved.