Exemplo n.º 1
0
void Mob::ProcessFlee()
{

	//Stop fleeing if effect is applied after they start to run.
	//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
	if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) &&
			!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
		curfp = false;
		return;
	}

	//see if we are still dying, if so, do nothing
	float fleeratio = GetSpecialAbility(FLEE_PERCENT);
	fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
	if (GetHPRatio() < fleeratio)
		return;

	//we are not dying anymore... see what we do next

	flee_mode = false;

	//see if we are legitimately feared or blind now
	if (!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
		//not feared or blind... were done...
		curfp = false;
		return;
	}
}
Exemplo n.º 2
0
bool Mob::CombatRange(Mob* other)
{
	if(!other)
		return(false);

	float size_mod = GetSize();
	float other_size_mod = other->GetSize();

	if(GetRace() == 49 || GetRace() == 158 || GetRace() == 196) //For races with a fixed size
		size_mod = 60.0f;
	else if (size_mod < 6.0)
		size_mod = 8.0f;

	if(other->GetRace() == 49 || other->GetRace() == 158 || other->GetRace() == 196) //For races with a fixed size
		other_size_mod = 60.0f;
	else if (other_size_mod < 6.0)
		other_size_mod = 8.0f;

	if (other_size_mod > size_mod)
	{
		size_mod = other_size_mod;
	}

	// this could still use some work, but for now it's an improvement....

	if (size_mod > 29)
		size_mod *= size_mod;
	else if (size_mod > 19)
		size_mod *= size_mod * 2;
	else
		size_mod *= size_mod * 4;


	// prevention of ridiculously sized hit boxes
	if (size_mod > 10000)
		size_mod = size_mod / 7;

	float _DistNoRoot = DistanceSquared(m_Position, other->GetPosition());

	if (GetSpecialAbility(NPC_CHASE_DISTANCE)){

		bool DoLoSCheck = true;
		float max_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0));
		float min_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1));

		if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2))
			DoLoSCheck = false; //Ignore line of sight check

		if (max_dist == 1)
			max_dist = 250.0f; //Default it to 250 if you forget to put a value

		max_dist = max_dist * max_dist;

		if (!min_dist)
			min_dist = size_mod; //Default to melee range
		else
			min_dist = min_dist * min_dist;

		if ((DoLoSCheck && CheckLastLosState()) && (_DistNoRoot >= min_dist && _DistNoRoot <= max_dist))
			SetPseudoRoot(true);
		else
			SetPseudoRoot(false);
	}

	if (_DistNoRoot <= size_mod)
	{
		return true;
	}
	return false;
}
Exemplo n.º 3
0
/*
	If you change this function, you should update the above function
	to keep the #aggro command accurate.
*/
bool Mob::CheckWillAggro(Mob *mob) {
	if(!mob)
		return false;

	//sometimes if a client has some lag while zoning into a dangerous place while either invis or a GM
	//they will aggro mobs even though it's supposed to be impossible, to lets make sure we've finished connecting
	if (mob->IsClient()) {
		if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn())
			return false;
	}

	Mob *ownr = mob->GetOwner();
	if(ownr && ownr->IsClient() && !ownr->CastToClient()->ClientFinishedLoading())
		return false;

	float iAggroRange = GetAggroRange();

	// Check If it's invisible and if we can see invis
	// Check if it's a client, and that the client is connected and not linkdead,
	// and that the client isn't Playing an NPC, with thier gm flag on
	// Check if it's not a Interactive NPC
	// Trumpcard: The 1st 3 checks are low cost calcs to filter out unnessecary distance checks. Leave them at the beginning, they are the most likely occurence.
	// Image: I moved this up by itself above faction and distance checks because if one of these return true, theres no reason to go through the other information

	float t1, t2, t3;
	t1 = mob->GetX() - GetX();
	t2 = mob->GetY() - GetY();
	t3 = mob->GetZ() - GetZ();
	//Cheap ABS()
	if(t1 < 0)
		t1 = 0 - t1;
	if(t2 < 0)
		t2 = 0 - t2;
	if(t3 < 0)
		t3 = 0 - t3;
	if(( t1 > iAggroRange)
		|| ( t2 > iAggroRange)
		|| ( t3 > iAggroRange)
		||(mob->IsInvisible(this))
		|| (mob->IsClient() &&
			(!mob->CastToClient()->Connected()
				|| mob->CastToClient()->IsLD()
				|| mob->CastToClient()->IsBecomeNPC()
				|| mob->CastToClient()->GetGM()
			)
		))
	{
		return(false);
	}

	// Don't aggro new clients if we are already engaged unless PROX_AGGRO is set
	if (IsEngaged() && (!GetSpecialAbility(PROX_AGGRO) || (GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)))) {
		Log.Out(Logs::Moderate, Logs::Aggro,
			"%s is in combat, and does not have prox_aggro, or does and is out of combat range with %s",
			GetName(), mob->GetName());
		return false;
	}

	//im not sure I understand this..
	//if I have an owner and it is not this mob, then I cannot
	//aggro this mob...???
	//changed to be 'if I have an owner and this is it'
	if(mob == GetOwner()) {
		return(false);
	}

	float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
	float iAggroRange2 = iAggroRange*iAggroRange;

	if( dist2 > iAggroRange2 ) {
		// Skip it, out of range
		return(false);
	}

	//Image: Get their current target and faction value now that its required
	//this function call should seem backwards
	FACTION_VALUE fv = mob->GetReverseFactionCon(this);

	// Make sure they're still in the zone
	// Are they in range?
	// Are they kos?
	// Are we stupid or are they green
	// and they don't have their gm flag on
	int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap
	if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE)
		heroicCHA_mod = THREATENLY_ARRGO_CHANCE;
	if
	(
	//old InZone check taken care of above by !mob->CastToClient()->Connected()
	(
		( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
		||( mob->IsClient() && mob->CastToClient()->IsSitting() )
		||( mob->GetLevelCon(GetLevel()) != CON_GREEN )

	)
	&&
	(
		(
			fv == FACTION_SCOWLS
			||
			(mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)
			||
			(
				fv == FACTION_THREATENLY
				&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
			)
		)
	)
	)
	{
		//FatherNiwtit: make sure we can see them. last since it is very expensive
		if(CheckLosFN(mob)) {
			Log.Out(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName());
			return( mod_will_aggro(mob, this) );
		}
	}

	Log.Out(Logs::Detail, Logs::Aggro, "Is In zone?:%d\n", mob->InZone());
	Log.Out(Logs::Detail, Logs::Aggro, "Dist^2: %f\n", dist2);
	Log.Out(Logs::Detail, Logs::Aggro, "Range^2: %f\n", iAggroRange2);
	Log.Out(Logs::Detail, Logs::Aggro, "Faction: %d\n", fv);
	Log.Out(Logs::Detail, Logs::Aggro, "Int: %d\n", GetINT());
	Log.Out(Logs::Detail, Logs::Aggro, "Con: %d\n", GetLevelCon(mob->GetLevel()));

	return(false);
}
Exemplo n.º 4
0
//this is called whenever we are damaged to process possible fleeing
void Mob::CheckFlee() {
	//if were allready fleeing, dont need to check more...
	if(flee_mode && curfp)
		return;

	//dont bother if we are immune to fleeing
	if(GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee)
		return;

	if(!flee_timer.Check())
		return;	//only do all this stuff every little while, since
				//its not essential that we start running RIGHT away

	//see if were possibly hurt enough
	float ratio = GetHPRatio();
	float fleeratio = GetSpecialAbility(FLEE_PERCENT);
	fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);

	if(ratio >= fleeratio)
		return;

	//we might be hurt enough, check con now..
	Mob *hate_top = GetHateTop();
	if(!hate_top) {
		//this should never happen...
		StartFleeing();
		return;
	}

	float other_ratio = hate_top->GetHPRatio();
	if(other_ratio < 20) {
		//our hate top is almost dead too... stay and fight
		return;
	}

	//base our flee ratio on our con. this is how the
	//attacker sees the mob, since this is all we can observe
	uint32 con = GetLevelCon(hate_top->GetLevel(), GetLevel());
	float run_ratio;
	switch(con) {
		//these values are not 100% researched
		case CON_GREEN:
			run_ratio = fleeratio;
			break;
		case CON_LIGHTBLUE:
			run_ratio = fleeratio * 9 / 10;
			break;
		case CON_BLUE:
			run_ratio = fleeratio * 8 / 10;
			break;
		default:
			run_ratio = fleeratio * 7 / 10;
			break;
	}
	if(ratio < run_ratio)
	{
		if (RuleB(Combat, FleeIfNotAlone) ||
			GetSpecialAbility(ALWAYS_FLEE) ||
			(!RuleB(Combat, FleeIfNotAlone) && (entity_list.GetHatedCount(hate_top, this) == 0)))
			StartFleeing();
	}
}