예제 #1
0
bool Map::LineIntersectsNode( NodeRef node_r, VERTEX p1, VERTEX p2, VERTEX *result, FACE **on) const {
	_ZP(Map_LineIntersectsNode);
	if( node_r == NODE_NONE || node_r >= m_Nodes) {
		return(true);   //can see through empty nodes, just allow LOS on error...
	}
	const PNODE _node = &mNodes[node_r];
	if(!(_node->flags & nodeFinal)) {
		return(true);   //not a final node... not sure best action
	}
	
	unsigned long i;
	
	PFACE cur;
	const uint32 *cfl = mFaceLists + _node->faces.offset;
	
	for(i = 0; i < _node->faces.count; i++) {
		if(*cfl > m_Faces)
			continue;	//watch for invalid lists, they seem to happen
		cur = &mFinalFaces[ *cfl ];
		if(LineIntersectsFace(cur,p1, p2, result)) {
			if(on != NULL)
				*on = cur;
			return(true);
		}
		cfl++;
	}

//printf("Checked %ld faces and found none in the way.\n", i);

	return(false);
}
예제 #2
0
tHateEntry *HateList::Find(Mob *ent)
{
	_ZP(HateList_Find);
    LinkedListIterator<tHateEntry*> iterator(list);
    iterator.Reset();
	while(iterator.MoreElements())
    {
        if(iterator.GetData()->ent == ent)
            return iterator.GetData();
        iterator.Advance();
    }
	return NULL;
}
예제 #3
0
Mob* HateList::GetDamageTop(Mob* hater)
{
	_ZP(HateList_GetDamageTop);
	Mob* current = NULL;
	Group* grp = NULL;
	Raid* r = NULL;
	uint32 dmg_amt = 0;

    LinkedListIterator<tHateEntry*> iterator(list);
    iterator.Reset();
	while(iterator.MoreElements())
    {
		grp = NULL;
		r = NULL;

		if(iterator.GetData()->ent && iterator.GetData()->ent->IsClient()){
			r = entity_list.GetRaidByClient(iterator.GetData()->ent->CastToClient());
		}

        grp = entity_list.GetGroupByMob(iterator.GetData()->ent);

		if(iterator.GetData()->ent && r){
			if(r->GetTotalRaidDamage(hater) >= dmg_amt)
			{
				current = iterator.GetData()->ent;
				dmg_amt = r->GetTotalRaidDamage(hater);
			}
		}
		else if (iterator.GetData()->ent != NULL && grp != NULL)
        {
			if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
            {
				current = iterator.GetData()->ent;
				dmg_amt = grp->GetTotalGroupDamage(hater);
            }
        }
        else if (iterator.GetData()->ent != NULL && (uint32)iterator.GetData()->damage >= dmg_amt)
        {
			current = iterator.GetData()->ent;
			dmg_amt = iterator.GetData()->damage;
        }
        iterator.Advance();
    }
	return current;
}
예제 #4
0
Mob *HateList::GetMostHate(){
	_ZP(HateList_GetMostHate);

	Mob* top = NULL;
	int32 hate = -1;

	LinkedListIterator<tHateEntry*> iterator(list);
	iterator.Reset();
	while(iterator.MoreElements())
	{
		tHateEntry *cur = iterator.GetData();
		if(cur->ent != NULL && (cur->hate > hate))
		{
			top = cur->ent;
			hate = cur->hate;
		}
		iterator.Advance();
	}
	return top;
}
예제 #5
0
void HateList::DoFactionHits(int32 nfl_id) {
	_ZP(HateList_DoFactionHits);
	if (nfl_id <= 0)
		return;
    LinkedListIterator<tHateEntry*> iterator(list);
    iterator.Reset();
	while(iterator.MoreElements())
    {
        Client *p;

        if (iterator.GetData()->ent && iterator.GetData()->ent->IsClient())
            p = iterator.GetData()->ent->CastToClient();
        else
            p = NULL;

        if (p)
			p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity());
        iterator.Advance();
    }
}
예제 #6
0
Mob* HateList::GetClosest(Mob *hater) {
	_ZP(HateList_GetClosest);
	Mob* close = NULL;
	float closedist = 99999.9f;
	float thisdist;
	
    LinkedListIterator<tHateEntry*> iterator(list);
    iterator.Reset();
	while(iterator.MoreElements()) {
		thisdist = iterator.GetData()->ent->DistNoRootNoZ(*hater);
		if(iterator.GetData()->ent != NULL && thisdist <= closedist) {
			closedist = thisdist;
			close = iterator.GetData()->ent;
		}
        iterator.Advance();
	}
	
	if (close == 0 && hater->IsNPC())
		close = hater->CastToNPC()->GetHateTop();
	
	return close;
}
예제 #7
0
파일: spawn2.cpp 프로젝트: josheb/emu_dc
bool Spawn2::Process() {
	_ZP(Spawn2_Process);

	IsDespawned = false;

	if(!Enabled())
		return true;

	//grab our spawn group
	SpawnGroup* sg = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);

	if(NPCPointerValid() && (sg->despawn == 0 || condition_id != 0))
		return true;

	if (timer.Check())	{
		timer.Disable();
		
		_log(SPAWNS__MAIN, "Spawn2 %d: Timer has triggered", spawn2_id);
		
		//first check our spawn condition, if this isnt active
		//then we reset the timer and try again next time.
		if(condition_id != SC_AlwaysEnabled 
			&& !zone->spawn_conditions.Check(condition_id, condition_min_value)) {
			_log(SPAWNS__CONDITIONS, "Spawn2 %d: spawning prevented by spawn condition %d", spawn2_id, condition_id);
			Reset();
			return(true);
		}
		
		if (sg == NULL) {
			database.LoadSpawnGroupsByID(spawngroup_id_,&zone->spawn_group_list);
			sg = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
		}

		if (sg == NULL) {
			_log(SPAWNS__MAIN, "Spawn2 %d: Unable to locate spawn group %d. Disabling.", spawn2_id, spawngroup_id_);
			return false;
		}
		
		//have the spawn group pick an NPC for us
		uint32 npcid = sg->GetNPCType();
		if (npcid == 0) {
			_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d did not yeild an NPC! not spawning.", spawn2_id, spawngroup_id_);
			Reset();	//try again later (why?)
			return(true);
		}
		
		//try to find our NPC type.
		const NPCType* tmp = database.GetNPCType(npcid);
		if (tmp == NULL) {
			_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded an invalid NPC type %d", spawn2_id, spawngroup_id_, npcid);
			Reset();	//try again later
			return(true);
		}

		if(tmp->unique_spawn_by_name)
		{
			if(!entity_list.LimitCheckName(tmp->name)) 
			{
				_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is unique and one already exists.", spawn2_id, spawngroup_id_, npcid);
				timer.Start(5000);	//try again in five seconds.
				return(true);
			}
		}

		if(tmp->spawn_limit > 0) {
			if(!entity_list.LimitCheckType(npcid, tmp->spawn_limit)) {
				_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is over its spawn limit (%d)", spawn2_id, spawngroup_id_, npcid, tmp->spawn_limit);
				timer.Start(5000);	//try again in five seconds.
				return(true);
			}
		}

		if(sg->despawn != 0 && condition_id == 0)
			zone->Despawn(spawn2_id);

		if(IsDespawned)
			return true;

		if(spawn2_id)
			database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), 0);
		
		currentnpcid = npcid;
		NPC* npc = new NPC(tmp, this, x, y, z, heading, FlyMode3);

		//DCBOOKMARK
		npc->mod_prespawn(this);

		npcthis = npc;
		npc->AddLootTable();
		npc->SetSp2(spawngroup_id_);
        npc->SaveGuardPointAnim(anim);
        npc->SetAppearance((EmuAppearance)anim);
		entity_list.AddNPC(npc);
		//this limit add must be done after the AddNPC since we need the entity ID.
		entity_list.LimitAddNPC(npc);
            if(sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay)
		npc->AI_SetRoambox(sg->roamdist,sg->roambox[0],sg->roambox[1],sg->roambox[2],sg->roambox[3],sg->delay);
		if(zone->InstantGrids()) {
			_log(SPAWNS__MAIN, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f).", spawn2_id, spawngroup_id_, npc->GetName(), npcid, x, y, z);
			LoadGrid();
		} else {
			_log(SPAWNS__MAIN, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f). Grid loading delayed.", spawn2_id, spawngroup_id_, tmp->name, npcid, x, y, z);
		}
	}
	return true;
}
예제 #8
0
//looking for any mob with hate > -1
bool HateList::IsEmpty() {
	_ZP(HateList_IsEmpty);
	
	return(list.Count() == 0);
}
예제 #9
0
Mob *HateList::GetTop(Mob *center)
{
	_ZP(HateList_GetTop);
	Mob* top = NULL;
	int32 hate = -1;
	
	if (RuleB(Aggro,SmartAggroList)){
		Mob* topClientInRange = NULL;
		int32 hateClientInRange = -1;
        int skipped_count = 0;

		LinkedListIterator<tHateEntry*> iterator(list);
		iterator.Reset();
		while(iterator.MoreElements())
		{
    		tHateEntry *cur = iterator.GetData();
			int16 aggroMod = 0;

			if(!cur){
				iterator.Advance();
				continue;
			}			

			if(!cur->ent){
				iterator.Advance();
				continue;
			}

            if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
                if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
                    skipped_count++;
                    iterator.Advance();
                    continue;
                }
            }

			if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
				if(hate == -1)
				{
					top = cur->ent;
					hate = 0;
				}
				iterator.Advance();
				continue;
			}

			int32 currentHate = cur->hate;

			if(cur->ent->IsClient()){
				
				if(cur->ent->CastToClient()->IsSitting()){
					aggroMod += RuleI(Aggro, SittingAggroMod);
				}

				if(center){
					if(center->GetTarget() == cur->ent)
						aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
					if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
					{
						if(center->CombatRange(cur->ent)){
							aggroMod += RuleI(Aggro, MeleeRangeAggroMod);

							if(currentHate > hateClientInRange || cur->bFrenzy){
								hateClientInRange = currentHate;
								topClientInRange = cur->ent;
							}
						}
					}
				}

			}
			else{
				if(center){
					if(center->GetTarget() == cur->ent)
						aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
					if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
					{
						if(center->CombatRange(cur->ent)){
							aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
						}
					}
				}
			}

			if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
				aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
			}

			if(aggroMod){
				currentHate += (currentHate * aggroMod / 100);
			}

			if(currentHate > hate || cur->bFrenzy){
				hate = currentHate;
				top = cur->ent;
			}

			iterator.Advance();
		}

		if(topClientInRange != NULL && top != NULL) {
			bool isTopClientType = top->IsClient();
#ifdef BOTS
			if(!isTopClientType) {
				if(top->IsBot()) {
					isTopClientType = true;
					topClientInRange = top;
				}
			}
#endif //BOTS
			if(!isTopClientType)
				return topClientInRange;

			return top;
        }
		else {
			if(top == NULL && skipped_count > 0) {
                return center->GetTarget();
            }
			return top;
        }
	}
	else{
		LinkedListIterator<tHateEntry*> iterator(list);
		iterator.Reset();
        int skipped_count = 0;
		while(iterator.MoreElements())
		{
    		tHateEntry *cur = iterator.GetData();
            if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
                if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
                    skipped_count++;
                    iterator.Advance();
                    continue;
                }
            }

			if(cur->ent != NULL && ((cur->hate > hate) || cur->bFrenzy ))
			{
				top = cur->ent;
				hate = cur->hate;
			}
			iterator.Advance();
		}
		if(top == NULL && skipped_count > 0) {
            return center->GetTarget();
        }
		return top;
	}
}
예제 #10
0
// Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
	_ZP(Database_AddLootTableToNPC);
//if (loottable_id == 178190)
//DebugBreak();
	const LootTable_Struct* lts = 0;
	*copper = 0;
	*silver = 0;
	*gold = 0;
	*plat = 0;

	lts = database.GetLootTable(loottable_id);
	if (!lts)
		return;

	// do coin
	if (lts->mincash > lts->maxcash) {
		std::cerr << "Error in loottable #" << loottable_id << ": mincash > maxcash" << std::endl;
	}
	else if (lts->maxcash != 0) {
		uint32 cash = 0;
		if (lts->mincash == lts->maxcash)
			cash = lts->mincash;
		else
			cash = MakeRandomInt(lts->mincash, lts->maxcash);
		if (cash != 0) {
			if (lts->avgcoin != 0) {
				//this is some crazy ass stuff... and makes very little sense... dont use it, k?
				uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
				uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
				*copper = MakeRandomInt(mincoin, maxcoin);
				*silver = MakeRandomInt(mincoin, maxcoin);
				*gold = MakeRandomInt(mincoin, maxcoin);
				if(*copper > cash) { *copper = cash; }
					cash -= *copper;
				if(*silver>(cash/10)) { *silver = (cash/10); }
					cash -= *silver*10;
				if(*gold > (cash/100)) { *gold = (cash/100); }
					cash -= *gold*100;
			}
			if (cash < 0) {
				cash = 0;
			}
			*plat = cash / 1000;
			cash -= *plat * 1000;
			uint32 gold2 = cash / 100;
			cash -= gold2 * 100;
			uint32 silver2 = cash / 10;
			cash -= silver2 * 10;
			*gold += gold2;
			*silver += silver2;
			*copper += cash;
		}
	}

	// Do items
	for (uint32 i=0; i<lts->NumEntries; i++) {
		for (uint32 k = 1; k <= lts->Entries[i].multiplier; k++) {
			uint8 droplimit = lts->Entries[i].droplimit;
			uint8 mindrop = lts->Entries[i].mindrop;

			//LootTable Entry probability
			float ltchance = 0.0f;
			ltchance = lts->Entries[i].probability;

			float drop_chance = 0.0f;
			if(ltchance > 0.0 && ltchance < 100.0) {
				drop_chance = MakeRandomFloat(0.0, 100.0);
			}

			if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
				AddLootDropToNPC(npc,lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
			}
		}
	}
}
예제 #11
0
float Map::FindBestZ( NodeRef node_r, VERTEX p1, VERTEX *result, FACE **on) const {
	_ZP(Map_FindBestZ);

	p1.z += RuleI(Map, FindBestZHeightAdjust);

	if(RuleB(Map, UseClosestZ))
		return FindClosestZ(p1);

	if(node_r == GetRoot()) {
		node_r = SeekNode(node_r, p1.x, p1.y);
	}
	if( node_r == NODE_NONE || node_r >= m_Nodes) {
		return(BEST_Z_INVALID);
	}
	const PNODE _node = &mNodes[node_r];
	if(!(_node->flags & nodeFinal)) {
		return(BEST_Z_INVALID);   //not a final node... could find the proper node...
	}
	
	VERTEX tmp_result;	//dummy placeholder if they do not ask for a result.
	if(result == NULL)
		result = &tmp_result;
	
	VERTEX p2(p1);
	p2.z = BEST_Z_INVALID;
	
	float best_z = BEST_Z_INVALID;
	int zAttempt;

	unsigned long i;

	PFACE cur;

	// If we don't find a bestZ on the first attempt, we try again from a position CurrentZ + 10 higher
	// This is in case the pathing between waypoints temporarily sends the NPC below ground level.
	// 
	for(zAttempt=1; zAttempt<=2; zAttempt++) {

		const uint32 *cfl = mFaceLists + _node->faces.offset;

#ifdef DEBUG_BEST_Z
printf("Start finding best Z...\n");
#endif
		for(i = 0; i < _node->faces.count; i++) {
			if(*cfl > m_Faces)
		               continue;       //watch for invalid lists, they seem to happen, e.g. in eastwastes.map

			cur = &mFinalFaces[ *cfl ];
//printf("Intersecting with face %lu\n", *cfl);
			if(LineIntersectsFace(cur, p1, p2, result)) {
#ifdef DEBUG_BEST_Z
					printf("  %lu (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)\n",
					*cfl, cur->a.x, cur->a.y, cur->a.z,
					cur->b.x, cur->b.y, cur->b.z, 
					cur->c.x, cur->c.y, cur->c.z);
					printf("Found a z: %.2f\n", result->z);
#endif
				if (result->z > best_z) {
					if(on != NULL)
						*on = cur;
					best_z = result->z;
				}
			}
			cfl++;
		}

		if(best_z != BEST_Z_INVALID) return best_z;

		 p1.z = p1.z + 10 ;   // If we can't find a best Z, the NPC is probably just under the world. Try again from 10 units higher up.
	}

#ifdef DEBUG_BEST_Z
fflush(stdout);
printf("Best Z found: %.2f\n", best_z);
#endif
	return best_z;
}
예제 #12
0
bool Map::LineIntersectsZone(VERTEX start, VERTEX end, float step_mag, VERTEX *result, FACE **on) const
{
	_ZP(Map_LineIntersectsZone);
	// Cast a ray from start to end, checking for collisions in each node between the two points.
	//
	float stepx, stepy, stepz, curx, cury, curz;

	curx = start.x;
	cury = start.y;
	curz = start.z;

	VERTEX cur = start;
		
	stepx = end.x - start.x;
	stepy = end.y - start.y;
	stepz = end.z - start.z;

	if((stepx == 0) && (stepy == 0) && (stepz == 0))
		return false;

	float factor =  sqrt(stepx*stepx + stepy*stepy + stepz*stepz);

	stepx = (stepx/factor)*step_mag;
	stepy = (stepy/factor)*step_mag;
	stepz = (stepz/factor)*step_mag;

	NodeRef cnode, lnode, finalnode;
	lnode = NODE_NONE;      //last node visited

	cnode = SeekNode(GetRoot(), start.x, start.y);
	finalnode = SeekNode(GetRoot(), end.x, end.y);
	if(cnode == finalnode)
		return LineIntersectsNode(cnode, start, end, result, on);

	do {

		stepx = (float)end.x - curx;
		stepy = (float)end.y - cury;
		stepz = (float)end.z - curz;

		factor =  sqrt(stepx*stepx + stepy*stepy + stepz*stepz);

		stepx = (stepx/factor)*step_mag;
		stepy = (stepy/factor)*step_mag;
		stepz = (stepz/factor)*step_mag;
			
	    	cnode = SeekNode(GetRoot(), curx, cury);
		if(cnode != lnode)
		{
 		    	lnode = cnode;

			if(cnode == NODE_NONE)
				return false;

			if(LineIntersectsNode(cnode, start, end, result, on))
       				return(true);
       	       		
			if(cnode == finalnode)
				return false;
		}
		curx += stepx;
		cury += stepy;
		curz += stepz;

		cur.x = curx;
		cur.y = cury;
		cur.z = curz;

		if(ABS(curx - end.x) < step_mag) cur.x = end.x;
		if(ABS(cury - end.y) < step_mag) cur.y = end.y;
		if(ABS(curz - end.z) < step_mag) cur.z = end.z;

	} while(cur.x != end.x || cur.y != end.y || cur.z != end.z);

	return false;
}