double solve() {
	int i,j,k,l,m;
	double x1,y1,x2,y2;
	/*	calculate distances and tangent points for each circle pair */
	for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++)
		dist[i][j][k][l]=-1;
	memset(theta1,0,sizeof(theta1));
	memset(theta2,0,sizeof(theta2));
	for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++) if(k!=l) {
		if(k==1) continue;
		if((k<2 && i) || (l<2 && j)) continue;
		twocircletangent(circlex[k],circley[k],circler[k],
			circlex[l],circley[l],circler[l],i,j,&x1,&y1,&x2,&y2);
		/*	for each other circle: check if it collides */
		for(m=0;m<n;m++)
			if(m!=k && m!=l && linecircleintersect(x1,y1,x2,y2,
				circlex[m],circley[m],circler[m])) goto fail;
//		printf("ix (%d %d) %d %d\n",i,j,k,l);printf("from circle (%.1f %.1f %d) to (%.1f %.1f %d): (%f %f) (%f %f)\n",circlex[k],circley[k],circler[k],circlex[l],circley[l],circler[l],x1,y1,x2,y2);printf("dist %.10f\n",dist2d(x1,y1,x2,y2));
		dist[i][j][k][l]=dist2d(x1,y1,x2,y2);
		tx1[i][j][k][l]=x1;
		ty1[i][j][k][l]=y1;
		tx2[i][j][k][l]=x2;
		ty2[i][j][k][l]=y2;
		theta1[i][j][k][l]=getangle(x1,y1,circlex[k],circley[k]);
		theta2[i][j][k][l]=getangle(x2,y2,circlex[l],circley[l]);
	fail:;
	}
//	for(i=0;i<2;i++) for(j=0;j<2;j++) for(k=0;k<n;k++) for(l=0;l<n;l++) if(dist[i][j][k][l]>-.5) {printf("%d %d %d %d: %f (%.3f %.3f) (%.3f %.3f) (%.2f %.2f)\n",i,j,k,l,dist[i][j][k][l],tx1[i][j][k][l],ty1[i][j][k][l],tx2[i][j][k][l],ty2[i][j][k][l],theta1[i][j][k][l],theta2[i][j][k][l]);}
	return dijkstra();
}
Exemple #2
0
int pointisccw(double x1, double y1, double x2, double y2, double px, double py) {
    double angle = getangle(x1, y1, x2, y2);
    double angle2 = getangle(x2, y2, px, py);
    if (normalizeangle(angle2-angle) > 0) {
        // point is to the "left" side -> counter-clockwise
        return 1;
    }
    // point is to the "right" side -> not counter-clockwise
    return 0;
}
Exemple #3
0
void work()
{
	nac = nzero = 0;
	for (int i = 0; i < n; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		pt[i] = {x, y, 0};
	}
	for (int i = 0; i < n; ++i) {
		std::memcpy(sorted, pt, n * sizeof(sorted[0]));
		std::swap(sorted[n - 1], sorted[i]);
		base = sorted[n - 1];
		for (int i = 0; i < n; ++i)
			sorted[i].angle = getangle(sorted[i] - base);
		std::sort(sorted, sorted + n - 1, [](const Point& a, const Point& b){
			//return cross(a - base, b - base) < 0;
			//return getangle(a - base) < getangle(b - base);
			return a.angle < b.angle;
		});
		//std::cout << "BASE " << base.x << ' ' << base.y << std::endl;
		//for (int j = 0; j < n - 1; ++j)
			//std::cout << j << ' ' << sorted[j].x << ' ' << sorted[j].y << std::endl;
		work2();
	}
	long long ttl = (long long) n * (n - 1) * (n - 2) / 2;
	long long fans = ttl - nac;
	//std::cout << "RESULT " << nac << ' ' << nzero << ' ' << ttl << std::endl;
	std::cout << ttl / 3 - fans << std::endl;
}
Exemple #4
0
void CPathFind::LookAt(position_t point)
{
	// don't look if i'm at that point
	if (!AtPoint(&point)){
		m_PTarget->loc.p.rotation = getangle(m_PTarget->loc.p, point);
	}
    m_PTarget->updatemask |= UPDATE_POS;
}
Exemple #5
0
short
SoundAngle(int x, int y)
{
    extern short screenpeek;

    short angle, delta_angle;

    angle = getangle(x - Player[screenpeek].posx, y - Player[screenpeek].posy);

    delta_angle = GetDeltaAngle(angle, Player[screenpeek].pang);

    // convert a delta_angle to a real angle if negative
    if (delta_angle < 0)
        delta_angle = NORM_ANGLE((1024 + delta_angle) + 1024);

    // convert 2048 degree angle to 32 degree angle
    return delta_angle >> 6;
}
void CEnmityContainer::LowerEnmityByPercent(CBattleEntity* PEntity, uint8 percent, CBattleEntity* HateReceiver)
{

    EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id);

    // current highest enmity before this update
    CBattleEntity* OldEntity = GetHighestEnmity();

    if (PEnmity != m_EnmityList.end() &&
        !m_EnmityList.key_comp()(PEntity->id, PEnmity->first))
    {
        float mod = ((float)(percent) / 100.0f);

        int32 CEValue = (float)(PEnmity->second->CE * mod);
        PEnmity->second->CE -= (CEValue < 0 ? 0 : CEValue);

        int32 VEValue = (float)(PEnmity->second->VE * mod);
        PEnmity->second->VE -= (VEValue < 0 ? 0 : VEValue);


        // transfer hate if HateReceiver not nullptr
        if (HateReceiver != nullptr)
        {
            UpdateEnmity(HateReceiver, 0, 0);
            EnmityList_t::iterator PEnmityReceiver = m_EnmityList.lower_bound(HateReceiver->id);
            PEnmityReceiver->second->CE = dsp_cap(PEnmityReceiver->second->CE + CEValue,1,10000);
            PEnmityReceiver->second->VE = dsp_cap(PEnmityReceiver->second->VE + VEValue,0,10000);
        }
    }

    // highest enmity holder after this update
    CBattleEntity* NewEntity = GetHighestEnmity();

    // PEntity is now the target, face the target
    if (OldEntity != NewEntity && !m_EnmityHolder->isAsleep())
    {
        if ((m_EnmityHolder->objtype == TYPE_MOB && !(((CMobEntity*)m_EnmityHolder)->m_Behaviour & BEHAVIOUR_NO_TURN)) || m_EnmityHolder->objtype != TYPE_MOB)
        {
            uint8 angle = getangle(m_EnmityHolder->loc.p, NewEntity->loc.p);
            m_EnmityHolder->loc.p.rotation = angle;
            m_EnmityHolder->loc.zone->PushPacket(m_EnmityHolder, CHAR_INRANGE, new CEntityUpdatePacket(m_EnmityHolder, ENTITY_UPDATE, UPDATE_POS));
        }
    }
}
void CEnmityContainer::LowerEnmityByPercent(CBattleEntity* PEntity, uint8 percent, CBattleEntity* HateReceiver)
{

	EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id);

	// current highest enmity before this update
	CBattleEntity* OldEntity = GetHighestEnmity();

    if( PEnmity != m_EnmityList.end() &&
       !m_EnmityList.key_comp()(PEntity->id, PEnmity->first))
	{
		float mod = ((float)(percent)/100.0f);

		int32 CEValue = (float)(PEnmity->second->CE * mod);
        PEnmity->second->CE -= (CEValue < 0 ? 0 : CEValue);

		int32 VEValue = (float)(PEnmity->second->VE * mod);
		PEnmity->second->VE -= (VEValue < 0 ? 0 : VEValue);


		// transfer hate if HateReceiver not null
		if (HateReceiver != NULL)
		{
			UpdateEnmity(HateReceiver,0,0);
			EnmityList_t::iterator PEnmityReceiver = m_EnmityList.lower_bound(HateReceiver->id);
			PEnmityReceiver->second->CE += CEValue;
			PEnmityReceiver->second->VE += VEValue;
		}
    }

	// highest enmity holder after this update
	CBattleEntity* NewEntity = GetHighestEnmity();

	// PEntity is now the target, face the target
	if (OldEntity != NewEntity && !m_EnmityHolder->isAsleep())
	{
		uint8 angle = getangle(m_EnmityHolder->loc.p, NewEntity->loc.p);
		m_EnmityHolder->loc.p.rotation = angle;
		m_EnmityHolder->loc.zone->PushPacket(m_EnmityHolder,CHAR_INRANGE, new CEntityUpdatePacket(m_EnmityHolder, ENTITY_UPDATE));
	}
}
void CAIMobDummy::ActionRoaming() 
{
	if (m_PMob->PEnmityContainer->GetHighestEnmity() != NULL)
	{
		m_ActionType = ACTION_ENGAGE;
		ActionEngage();
	}
	else if (m_PMob->m_OwnerID != 0)
	{
		uint16 TargID = m_PMob->m_OwnerID & 0x0FFF;
		m_PBattleTarget = (CBattleEntity*)m_PMob->loc.zone->GetEntity(TargID, TYPE_PC | TYPE_MOB | TYPE_PET);

        // TODO: возможно необходимо добавлять цели базовое количество ненависти

		m_ActionType = ACTION_ENGAGE;
		ActionEngage();
	}
	else if ((m_Tick - m_LastActionTime) > 45000 && m_PMob->m_Type != MOBTYPE_EVENT) 
	{	
		m_LastActionTime = m_Tick - rand()%30000;

		position_t RoamingPoint;

		RoamingPoint.x = m_PMob->m_SpawnPoint.x - 1 + rand()%2;
		RoamingPoint.y = m_PMob->m_SpawnPoint.y;
		RoamingPoint.z = m_PMob->m_SpawnPoint.z - 1 + rand()%2;

		m_PMob->loc.p.rotation = getangle(m_PMob->loc.p, RoamingPoint);

		battleutils::MoveTo(m_PMob, RoamingPoint, 1);

		m_PMob->loc.zone->PushPacket(m_PMob,CHAR_INRANGE, new CEntityUpdatePacket(m_PMob,ENTITY_UPDATE));
	}
	if (m_PMob->GetDespawnTimer() > 0 && m_PMob->GetDespawnTimer() < m_Tick)
	{
		m_LastActionTime = m_Tick - 12000; 
		m_PMob->PBattleAI->SetCurrentAction(ACTION_DEATH);
	}
}
void CMobController::Move()
{
    if (!PMob->PAI->CanFollowPath())
    {
        return;
    }
    float currentDistance = distance(PMob->loc.p, PTarget->loc.p);
    if (PMob->PAI->PathFind->IsFollowingScriptedPath() && PMob->PAI->CanFollowPath())
    {
        PMob->PAI->PathFind->FollowPath();
        return;
    }

    // attempt to teleport
    if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 1)
    {
        if (m_Tick >= m_LastSpecialTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_TELEPORT_CD)))
        {
            CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

            if (teleportBegin)
            {
                m_LastSpecialTime = m_Tick;
                MobSkill(PMob->targid, teleportBegin->getID());
            }
        }
    }

    bool move = PMob->PAI->PathFind->IsFollowingPath();
    float attack_range = PMob->m_ModelSize;

    if (PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST) > 0)
    {
        auto skillList {battleutils::GetMobSkillList(PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST))};

        if (!skillList.empty())
        {
            auto skill {battleutils::GetMobSkill(skillList.front())};
            if (skill)
            {
                attack_range = skill->getDistance();
            }
        }
    }

    if (PMob->getMobMod(MOBMOD_SHARE_POS) > 0)
    {
        CMobEntity* posShare = (CMobEntity*)PMob->GetEntity(PMob->getMobMod(MOBMOD_SHARE_POS) + PMob->targid, TYPE_MOB);
        PMob->loc = posShare->loc;
    }
    else if (((distance(PMob->loc.p, PTarget->loc.p) > attack_range - 0.2f) || move) && PMob->PAI->CanFollowPath())
    {
        //#TODO: can this be moved to scripts entirely?
        if (PMob->getMobMod(MOBMOD_DRAW_IN) > 0)
        {
            if (currentDistance >= PMob->m_ModelSize * 2)
                battleutils::DrawIn(PTarget, PMob, PMob->m_ModelSize - 0.2f);
        }
        if (PMob->speed != 0 && PMob->getMobMod(MOBMOD_NO_MOVE) == 0 && m_Tick >= m_LastSpecialTime)
        {
            // attempt to teleport to target (if in range)
            if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 2)
            {
                CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

                if (teleportBegin && currentDistance <= teleportBegin->getDistance())
                {
                    MobSkill(PMob->targid, teleportBegin->getID());
                    m_LastSpecialTime = m_Tick;
                    return;
                }
            }
            else if (CanMoveForward(currentDistance))
            {
                if (!PMob->PAI->PathFind->IsFollowingPath() || distanceSquared(PMob->PAI->PathFind->GetDestination(), PTarget->loc.p) > 10)
                {
                    //path to the target if we don't have a path already
                    PMob->PAI->PathFind->PathInRange(PTarget->loc.p, attack_range - 0.2f, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                }
                PMob->PAI->PathFind->FollowPath();
                if (!PMob->PAI->PathFind->IsFollowingPath())
                {
                    //arrived at target - move if there is another mob under me
                    if (PTarget->objtype == TYPE_PC)
                    {
                        for (auto PSpawnedMob : static_cast<CCharEntity*>(PTarget)->SpawnMOBList)
                        {
                            if (PSpawnedMob.second != PMob && !PSpawnedMob.second->PAI->PathFind->IsFollowingPath() && distance(PSpawnedMob.second->loc.p, PMob->loc.p) < 1.f)
                            {
                                auto angle = getangle(PMob->loc.p, PTarget->loc.p) + 64;
                                position_t new_pos {0, PMob->loc.p.x - (cosf(rotationToRadian(angle)) * 1.5f),
                                    PTarget->loc.p.y, PMob->loc.p.z + (sinf(rotationToRadian(angle)) * 1.5f), 0};
                                if (PMob->PAI->PathFind->ValidPosition(new_pos))
                                {
                                    PMob->PAI->PathFind->PathTo(new_pos, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                FaceTarget();
            }
        }
    }
    else
    {
        FaceTarget();
    }
}
Exemple #10
0
int xyzsound(short num,short i,long x,long y,long z)
{
    long sndist, cx, cy, cz, j,k;
    short pitche,pitchs,cs;
    int voice, sndang, ca, pitch;

//    if(num != 358) return 0;

    if( num >= NUM_SOUNDS ||
        FXDevice < 0 ||
        ( (soundm[num]&8) && ud.lockout ) ||
        SoundToggle == 0 ||
        Sound[num].num > 3 ||
        FX_VoiceAvailable(soundpr[num]) == 0 ||
        (ps[myconnectindex].timebeforeexit > 0 && ps[myconnectindex].timebeforeexit <= 26*3) ||
        ps[myconnectindex].gm&MODE_MENU) return -1;

    if( soundm[num]&128 )
    {
        sound(num);
        return 0;
    }

    if( soundm[num]&4 )
    {
        if(VoiceToggle==0 || (ud.multimode > 1 && PN == APLAYER && sprite[i].yvel != screenpeek && ud.coop != 1) ) return -1;

        for(j=0;j<NUM_SOUNDS;j++)
          for(k=0;k<Sound[j].num;k++)
            if( (Sound[j].num > 0) && (soundm[j]&4) )
              return -1;
    }

    cx = ps[screenpeek].oposx;
    cy = ps[screenpeek].oposy;
    cz = ps[screenpeek].oposz;
    cs = ps[screenpeek].cursectnum;
    ca = ps[screenpeek].ang+ps[screenpeek].look_ang;

    sndist = FindDistance3D((cx-x),(cy-y),(cz-z)>>4);

    if( i >= 0 && (soundm[num]&16) == 0 && PN == MUSICANDSFX && SLT < 999 && (sector[SECT].lotag&0xff) < 9 )
        sndist = divscale14(sndist,(SHT+1));

    pitchs = soundps[num];
    pitche = soundpe[num];
    j = klabs(pitche-pitchs);

    if(j)
    {
        if( pitchs < pitche )
             pitch = pitchs + ( rand()%j );
        else pitch = pitche + ( rand()%j );
    }
    else pitch = pitchs;

    sndist += soundvo[num];
    if(sndist < 0) sndist = 0;
    if( sndist && PN != MUSICANDSFX && !cansee(cx,cy,cz-(24<<8),cs,SX,SY,SZ-(24<<8),SECT) )
        sndist += sndist>>5;

    switch(num)
    {
        case PIPEBOMB_EXPLODE:
        case LASERTRIP_EXPLODE:
        case RPG_EXPLODE:
            if(sndist > (6144) )
                sndist = 6144;
            if(sector[ps[screenpeek].cursectnum].lotag == 2)
                pitch -= 1024;
            break;
        default:
            if(sector[ps[screenpeek].cursectnum].lotag == 2 && (soundm[num]&4) == 0)
                pitch = -768;
            if( sndist > 31444 && PN != MUSICANDSFX)
                return -1;
            break;
    }


    if( Sound[num].num > 0 && PN != MUSICANDSFX )
    {
        if( SoundOwner[num][0].i == i ) stopsound(num);
        else if( Sound[num].num > 1 ) stopsound(num);
        else if( badguy(&sprite[i]) && sprite[i].extra <= 0 ) stopsound(num);
    }

    if( PN == APLAYER && sprite[i].yvel == screenpeek )
    {
        sndang = 0;
        sndist = 0;
    }
    else
    {
        sndang = 2048 + ca - getangle(cx-x,cy-y);
        sndang &= 2047;
    }

    if(Sound[num].ptr == 0) { if( loadsound(num) == 0 ) return 0; }
    else
    {
       if (Sound[num].lock < 200)
          Sound[num].lock = 200;
       else Sound[num].lock++;
    }

    if( soundm[num]&16 ) sndist = 0;

    if(sndist < ((255-LOUDESTVOLUME)<<6) )
        sndist = ((255-LOUDESTVOLUME)<<6);

    if( soundm[num]&1 )
    {
        if(Sound[num].num > 0) return -1;

        voice = FX_PlayLoopedAuto( Sound[num].ptr, soundsiz[num], 0, -1,
                    pitch,sndist>>6,sndist>>6,0,soundpr[num],num);
    }
    else
    {
void CAIMobDummy::ActionAttack() 
{
	m_PBattleTarget = m_PMob->PEnmityContainer->GetHighestEnmity();

	if (m_PBattleTarget == NULL)
	{
        m_ActionType = ACTION_DISENGAGE;
		return; 
	}
	if (m_PBattleTarget->isDead())
	{
        if (m_PMob->m_OwnerID == m_PBattleTarget->id)
        {
            m_PMob->m_OwnerID = 0;
        }
		m_PMob->PEnmityContainer->Clear(m_PBattleTarget->id);
		ActionAttack();
		return;
	}

    m_PMob->loc.p.rotation = getangle(m_PMob->loc.p, m_PBattleTarget->loc.p);

    if (m_PMob->PParty != NULL)
    {
        for (uint16 i = 0; i < m_PMob->PParty->members.size(); ++i)
        {
            CMobEntity* PPartyMember = (CMobEntity*)m_PMob->PParty->members[i];

            if (PPartyMember->PBattleAI->GetCurrentAction() == ACTION_ROAMING &&
                distance(m_PMob->loc.p, PPartyMember->loc.p) < 10)
            {
                PPartyMember->PEnmityContainer->AddBaseEnmity(m_PBattleTarget);
            }
        }
    }

	if (distance(m_PMob->loc.p, m_PBattleTarget->loc.p) <= m_PMob->m_ModelSize)
	{
		if ((m_Tick - m_LastActionTime) > m_PMob->m_Weapons[SLOT_MAIN]->getDelay())
		{
			if (battleutils::IsParalised(m_PMob)) 
			{
				m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CMessageBasicPacket(m_PMob,m_PBattleTarget,0,0,29));
			}
			else if (battleutils::IsIntimidated(m_PMob, m_PBattleTarget)) 
			{
				m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CMessageBasicPacket(m_PMob,m_PBattleTarget,0,0,106));
			}
			else
			{
				if (m_PMob->health.tp > 100 && rand()%100 > 55) 
				{
					m_ActionType = ACTION_MOBABILITY_START;
                    ActionAbilityStart();
					return;
				}

				apAction_t Action;
                m_PMob->m_ActionList.clear();

				Action.ActionTarget = m_PBattleTarget;
				Action.reaction   = REACTION_EVADE;
				Action.speceffect = SPECEFFECT_NONE;
				Action.animation  = 0;
				Action.param	  = 0;
				Action.messageID  = 15;
				Action.flag		  = 0;

				uint16 damage = 0;

				if (m_PBattleTarget->StatusEffectContainer->HasStatusEffect(EFFECT_PERFECT_DODGE))
				{
					Action.messageID = 32; 
				}
				else if ( rand()%90 < battleutils::GetHitRate(m_PMob, m_PBattleTarget) )
				{
                    if (battleutils::IsAbsorbByShadow(m_PBattleTarget)) 
					{
                        Action.messageID = 0;
                        m_PBattleTarget->loc.zone->PushPacket(m_PBattleTarget,CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PBattleTarget,m_PBattleTarget,0,1,31));
					}
					else
					{
						Action.reaction   = REACTION_HIT;
						Action.speceffect = SPECEFFECT_HIT;
						Action.messageID  = 1;

						float DamageRatio = battleutils::GetDamageRatio(m_PMob, m_PBattleTarget); 

						if ( rand()%100 < battleutils::GetCritHitRate(m_PMob, m_PBattleTarget) )
						{
							DamageRatio += 1;
							DamageRatio = (DamageRatio > 3 ? 3 : DamageRatio);

							Action.speceffect = SPECEFFECT_CRITICAL_HIT;
							Action.messageID  = 67;
						}
						damage = (uint16)((m_PMob->m_Weapons[SLOT_MAIN]->getDamage() + battleutils::GetFSTR(m_PMob, m_PBattleTarget)) * DamageRatio);
					}
				}
                else if (m_PBattleTarget->objtype == TYPE_PC)
				{
					charutils::TrySkillUP((CCharEntity*)m_PBattleTarget, SKILL_EVA, m_PMob->GetMLevel());
				}
				Action.param = battleutils::TakePhysicalDamage(m_PMob, m_PBattleTarget, damage);

				m_PMob->m_ActionList.push_back(Action);
                m_PMob->PEnmityContainer->UpdateEnmityFromAttack(m_PBattleTarget, Action.param);

				m_PMob->loc.zone->PushPacket(m_PMob, CHAR_INRANGE, new CActionPacket(m_PMob));
			}
            m_LastActionTime = m_Tick;
		}
	}
	else
    {
		battleutils::MoveTo(m_PMob, m_PBattleTarget->loc.p, 2);
	}
	m_PMob->loc.zone->PushPacket(m_PMob,CHAR_INRANGE, new CEntityUpdatePacket(m_PMob, ENTITY_UPDATE));
}
void CMobController::DoCombatTick(time_point tick)
{
    HandleEnmity();
    PTarget = static_cast<CBattleEntity*>(PMob->GetEntity(PMob->GetBattleTargetID()));

    if (TryDeaggro())
    {
        Disengage();
        return;
    }

    TryLink();

    float currentDistance = distance(PMob->loc.p, PTarget->loc.p);

    if (!(PMob->m_Behaviour & BEHAVIOUR_NO_TURN))
    {
        PMob->PAI->PathFind->LookAt(PTarget->loc.p);
    }

    luautils::OnMobFight(PMob, PTarget);

    // Try to spellcast (this is done first so things like Chainspell spam is prioritised over TP moves etc.
    if (IsSpecialSkillReady(currentDistance) && TrySpecialSkill())
    {
        return;
    }
    else if (IsSpellReady(currentDistance) && TryCastSpell())
    {
        return;
    }
    else if (m_Tick >= m_LastMobSkillTime && dsprand::GetRandomNumber(100) < PMob->TPUseChance() && MobSkill())
    {
        return;
    }

    if (PMob->PAI->PathFind->IsFollowingScriptedPath() && PMob->PAI->CanFollowPath())
    {
        PMob->PAI->PathFind->FollowPath();
        return;
    }

    // attempt to teleport
    if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 1)
    {
        if (m_Tick >= m_LastSpecialTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_TELEPORT_CD)))
        {
            CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

            if (teleportBegin)
            {
                m_LastSpecialTime = m_Tick;
                MobSkill(PMob->targid, teleportBegin->getID());
            }
        }
    }

    bool move = PMob->PAI->PathFind->IsFollowingPath();
    float attack_range = PMob->m_ModelSize;

    if (PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST) > 0)
    {
        auto skillList {battleutils::GetMobSkillList(PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST))};

        if (!skillList.empty())
        {
            auto skill {battleutils::GetMobSkill(skillList.front())};
            if (skill)
            {
                attack_range = skill->getDistance();
            }
        }
    }

    if (PMob->getMobMod(MOBMOD_SHARE_POS) > 0)
    {
        CMobEntity* posShare = (CMobEntity*)PMob->GetEntity(PMob->getMobMod(MOBMOD_SHARE_POS) + PMob->targid, TYPE_MOB);
        PMob->loc = posShare->loc;
    }
    else if (((distance(PMob->loc.p, PTarget->loc.p) > attack_range - 0.2f) || move) && PMob->PAI->CanFollowPath())
    {
        //#TODO: can this be moved to scripts entirely?
        if (PMob->getMobMod(MOBMOD_DRAW_IN) > 0)
        {
            if (currentDistance >= PMob->m_ModelSize * 2)
                battleutils::DrawIn(PTarget, PMob, PMob->m_ModelSize - 0.2f);
        }
        if (PMob->speed != 0 && m_Tick >= m_LastSpecialTime)
        {
            // attempt to teleport to target (if in range)
            if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 2)
            {
                CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

                if (teleportBegin && currentDistance <= teleportBegin->getDistance())
                {
                    MobSkill(PMob->targid, teleportBegin->getID());
                    m_LastSpecialTime = m_Tick;
                    return;
                }
            }
            else if (CanMoveForward(currentDistance))
            {
                if (!PMob->PAI->PathFind->IsFollowingPath())
                {
                    //path to the target if we don't have a path already
                    PMob->PAI->PathFind->PathInRange(PTarget->loc.p, attack_range - 0.2f, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                }
                PMob->PAI->PathFind->FollowPath();
                if (!PMob->PAI->PathFind->IsFollowingPath())
                {
                    //arrived at target - move if there is another mob under me
                    if (PTarget->objtype == TYPE_PC)
                    {
                        for (auto PSpawnedMob : static_cast<CCharEntity*>(PTarget)->SpawnMOBList)
                        {
                            if (PSpawnedMob.second != PMob && !PSpawnedMob.second->PAI->PathFind->IsFollowingPath() && distance(PSpawnedMob.second->loc.p, PMob->loc.p) < 1.f)
                            {
                                auto angle = getangle(PMob->loc.p, PTarget->loc.p) + 64;
                                position_t new_pos {0, PMob->loc.p.x - (cosf(rotationToRadian(angle)) * 1.5f),
                                    PTarget->loc.p.y, PMob->loc.p.z + (sinf(rotationToRadian(angle)) * 1.5f), 0};
                                if (PMob->PAI->PathFind->ValidPosition(new_pos))
                                {
                                    PMob->PAI->PathFind->PathTo(new_pos, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}
Exemple #13
0
void move_p1_to_p2(double& x1, double& y1, const double& x2, const double& y2, const double& speed) {

	x1 += speed*cos(getangle(x1, y1, x2, y2));
	y1 += speed*sin(getangle(x1, y1, x2, y2));//yは画面の上のほうが小さいのでマイナス
}
int WallBreakPosition(short hitwall, short *sectnum, long *x, long *y, long *z, short *ang)
    {
    short w,nw;
    WALLp wp;
    long nx,ny;
    short wall_ang; 
    long ret=0;
    
    w = hitwall;
    wp = &wall[w];
    
    nw = wall[w].point2;
    wall_ang = NORM_ANGLE(getangle(wall[nw].x - wall[w].x, wall[nw].y - wall[w].y)+512);

    *sectnum = SectorOfWall(w);
    ASSERT(*sectnum >= 0);
    
    // midpoint of wall
    *x = DIV2(wall[w].x + wall[w].x);
    *y = DIV2(wall[w].y + wall[w].y);

    //getzsofsector(*sectnum, *x, *y, cz, fz);
    
    if (wp->nextwall < 0)
        {
        // white wall
        *z = DIV2(sector[*sectnum].floorz + sector[*sectnum].ceilingz);
        }
    else
        {
        short next_sectnum = wp->nextsector;
        
        // red wall
        ASSERT(wp->nextsector >= 0);
        
        // floor and ceiling meet
        if (sector[next_sectnum].floorz == sector[next_sectnum].ceilingz)
            *z = DIV2(sector[*sectnum].floorz + sector[*sectnum].ceilingz);
        else
        // floor is above other sector
        if (sector[next_sectnum].floorz < sector[*sectnum].floorz)
            *z = DIV2(sector[next_sectnum].floorz + sector[*sectnum].floorz);
        else    
        // ceiling is below other sector
        if (sector[next_sectnum].ceilingz > sector[*sectnum].ceilingz)
            *z = DIV2(sector[next_sectnum].ceilingz + sector[*sectnum].ceilingz);
        }    
    
    *ang = wall_ang;
    
    nx = MOVEx(128, wall_ang);
    ny = MOVEy(128, wall_ang);
    
    *x += nx;
    *y += ny;
    
    updatesectorz(*x,*y,*z,sectnum);
    if (*sectnum < 0)
        {
        *x = MAXLONG;  // don't spawn shrap, just change wall
        return(FALSE);
        }
        
    return(TRUE);
    }
static inline int32_t S_GetAngle(int32_t camang, const vec3_t *cam, const vec3_t *pos)
{
    return (2048 + camang - getangle(cam->x-pos->x, cam->y-pos->y))&2047;
}