void SetData64(uint32 uiType, uint64 uiData) { switch(uiType) { case TYPE_PLAYER_HOVER: if(!isFlying(uiData)) { Unit* pUnit = Unit::GetUnit(*(instance->GetCreature(m_uiMalygosGUID)), uiData); if(pUnit && pUnit->GetTypeId() == TYPEID_PLAYER) { m_flyingPlayers.push_back(uiData); //Using packet workaround WorldPacket data(12); data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); data.append(pUnit->GetPackGUID()); data << uint32(0); pUnit->SendMessageToSet(&data, true); } } break; case TYPE_SET_PLAYER_TO_CHECK: m_uiPlayerCheckGUID = uiData; break; } }
void LeprechaunController::throwCane() { if (!cane->isEnabled() && !isCaneHit() && !isFlying() && !isStoneHit()) { timers[TimerType::cane] = configTimers[TimerType::cane]; setBeginFlag(LeprechaunFlag::caneAnimation, true); } }
void LeprechaunController::kick() { if (!isCaneHit() && !isFlying() && !isStoneHit()) { timers[TimerType::kick] = configTimers[TimerType::kick]; setBeginFlag(LeprechaunFlag::kickAnimation, true); } }
void LeprechaunController::setMoving(const Vector3& movingDirection) { if (!isCaneHit() && !isFlying()) { this->movingDirection = movingDirection; setFlag(LeprechaunFlag::moving, movingDirection.lengthSquared() != 0); } }
void ARDrone::AT_FTRIM() { if (isFlying()) return; std::ostringstream oss; oss << "AT*FTRIM=" << m_indexCmd++ << "\r"; m_connectionsHandler->sendATCommand(oss.str()); }
void LeprechaunController::throwHat(float hatCharging) { if (!hat->isEnabled() && !isCaneHit() && !isFlying() && !isStoneHit()) { timers[TimerType::hat] = configTimers[TimerType::hat]; this->hatCharging = MathHelper::saturate(hatCharging); setBeginFlag(LeprechaunFlag::hatAnimation, true); } }
uint32 GetData(uint32 uiType) { switch(uiType) { case TYPE_MALYGOS: return m_auiEncounter[0]; case TYPE_OUTRO_CHECK: return m_uiOutroCheck; case TYPE_DESTROY_PLATFORM: return m_uiMalygosPlatformData; case TYPE_VORTEX: return m_bVortex; case TYPE_CHECK_PLAYER_FLYING: return isFlying(m_uiPlayerCheckGUID); } return 0; }
/* Fire a weapon at something */ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, int weapon_slot) { WEAPON_STATS *psStats; UDWORD firePause; SDWORD longRange; int compIndex; CHECK_OBJECT(psAttacker); CHECK_OBJECT(psTarget); ASSERT(psWeap != NULL, "Invalid weapon pointer"); /* Watermelon:dont shoot if the weapon_slot of a vtol is empty */ if (psAttacker->type == OBJ_DROID && isVtolDroid(((DROID *)psAttacker))) { if (psWeap->usedAmmo >= getNumAttackRuns(((DROID *)psAttacker), weapon_slot)) { objTrace(psAttacker->id, "VTOL slot %d is empty", weapon_slot); return false; } } /* Get the stats for the weapon */ compIndex = psWeap->nStat; ASSERT_OR_RETURN( false , compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); psStats = asWeaponStats + compIndex; // check valid weapon/prop combination if (!validTarget(psAttacker, psTarget, weapon_slot)) { return false; } unsigned fireTime = gameTime - deltaGameTime + 1; // Can fire earliest at the start of the tick. // See if reloadable weapon. if (psStats->reloadTime) { unsigned reloadTime = psWeap->lastFired + weaponReloadTime(psStats, psAttacker->player); if (psWeap->ammo == 0) // Out of ammo? { fireTime = std::max(fireTime, reloadTime); // Have to wait for weapon to reload before firing. if (gameTime < fireTime) { return false; } } if (reloadTime <= fireTime) { //reset the ammo level psWeap->ammo = psStats->numRounds; } } /* See when the weapon last fired to control it's rate of fire */ firePause = weaponFirePause(psStats, psAttacker->player); firePause = std::max(firePause, 1u); // Don't shoot infinitely many shots at once. fireTime = std::max(fireTime, psWeap->lastFired + firePause); if (gameTime < fireTime) { /* Too soon to fire again */ return false; } if (psTarget->visible[psAttacker->player] != UBYTE_MAX) { // Can't see it - can't hit it objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target", psAttacker->id, psStats->pName, psTarget->id); return false; } /* Check we can hit the target */ bool tall = (psAttacker->type == OBJ_DROID && isVtolDroid((DROID *)psAttacker)) || (psAttacker->type == OBJ_STRUCTURE && ((STRUCTURE *)psAttacker)->pStructureType->height > 1); if (proj_Direct(psStats) && !lineOfFire(psAttacker, psTarget, weapon_slot, tall)) { // Can't see the target - can't hit it with direct fire objTrace(psAttacker->id, "combFire(%u[%s]->%u): No direct line of sight to target", psAttacker->id, objInfo(psAttacker), psTarget->id); return false; } Vector3i deltaPos = psTarget->pos - psAttacker->pos; // if the turret doesn't turn, check if the attacker is in alignment with the target if (psAttacker->type == OBJ_DROID && !psStats->rotate) { uint16_t targetDir = iAtan2(removeZ(deltaPos)); int dirDiff = abs(angleDelta(targetDir - psAttacker->rot.direction)); if (dirDiff > FIXED_TURRET_DIR) { return false; } } /* Now see if the target is in range - also check not too near */ int dist = iHypot(removeZ(deltaPos)); longRange = proj_GetLongRange(psStats); int min_angle = 0; // Calculate angle for indirect shots if (!proj_Direct(psStats) && dist > 0) { min_angle = arcOfFire(psAttacker,psTarget,weapon_slot,true); // prevent extremely steep shots min_angle = std::min(min_angle, DEG(PROJ_ULTIMATE_PITCH)); // adjust maximum range of unit if forced to shoot very steep if (min_angle > DEG(PROJ_MAX_PITCH)) { //do not allow increase of max range though if (iSin(2*min_angle) < iSin(2*DEG(PROJ_MAX_PITCH))) // If PROJ_MAX_PITCH == 45, then always iSin(2*min_angle) <= iSin(2*DEG(PROJ_MAX_PITCH)), and the test is redundant. { longRange = longRange * iSin(2*min_angle) / iSin(2*DEG(PROJ_MAX_PITCH)); } } } int baseHitChance = 0; if (dist <= longRange && dist >= psStats->minRange) { // get weapon chance to hit in the long range baseHitChance = weaponLongHit(psStats,psAttacker->player); // adapt for height adjusted artillery shots if (min_angle > DEG(PROJ_MAX_PITCH)) { baseHitChance = baseHitChance * iCos(min_angle) / iCos(DEG(PROJ_MAX_PITCH)); } } else { /* Out of range */ objTrace(psAttacker->id, "combFire(%u[%s]->%u): Out of range", psAttacker->id, psStats->pName, psTarget->id); return false; } // apply experience accuracy modifiers to the base //hit chance, not to the final hit chance int resultHitChance = baseHitChance; // add the attacker's experience if (psAttacker->type == OBJ_DROID) { SDWORD level = getDroidEffectiveLevel((DROID *) psAttacker); // increase total accuracy by EXP_ACCURACY_BONUS % for each experience level resultHitChance += EXP_ACCURACY_BONUS * level * baseHitChance / 100; } // subtract the defender's experience if (psTarget->type == OBJ_DROID) { SDWORD level = getDroidEffectiveLevel((DROID *) psTarget); // decrease weapon accuracy by EXP_ACCURACY_BONUS % for each experience level resultHitChance -= EXP_ACCURACY_BONUS * level * baseHitChance / 100; } // fire while moving modifiers if (psAttacker->type == OBJ_DROID && ((DROID *)psAttacker)->sMove.Status != MOVEINACTIVE) { switch (psStats->fireOnMove) { case FOM_NO: // Can't fire while moving return false; break; case FOM_PARTIAL: resultHitChance = FOM_PARTIAL_ACCURACY_PENALTY * resultHitChance / 100; break; case FOM_YES: // can fire while moving break; } } /* -------!!! From that point we are sure that we are firing !!!------- */ // Add a random delay to the next shot. // TODO Add deltaFireTime to the time it takes to fire next. If just adding to psWeap->lastFired, it might put it in the future, causing assertions. And if not sometimes putting it in the future, the fire rate would be lower than advertised. //int fireJitter = firePause/100; // ±1% variation in fire rate. //int deltaFireTime = gameRand(fireJitter*2 + 1) - fireJitter; /* note when the weapon fired */ psWeap->lastFired = fireTime; /* reduce ammo if salvo */ if (psStats->reloadTime) { psWeap->ammo--; } // increment the shots counter psWeap->shotsFired++; // predicted X,Y offset per sec Vector3i predict = psTarget->pos; //Watermelon:Target prediction if (isDroid(psTarget) && castDroid(psTarget)->sMove.bumpTime == 0) { DROID *psDroid = castDroid(psTarget); int32_t flightTime; if (proj_Direct(psStats) || dist <= psStats->minRange) { flightTime = dist * GAME_TICKS_PER_SEC / psStats->flightSpeed; } else { int32_t vXY, vZ; // Unused, we just want the flight time. flightTime = projCalcIndirectVelocities(dist, deltaPos.z, psStats->flightSpeed, &vXY, &vZ, min_angle); } if (psTarget->lastHitWeapon == WSC_EMP) { int playerEmpTime = getEmpDisableTime(psTarget->player); int empTime = playerEmpTime - (gameTime - psTarget->timeLastHit); CLIP(empTime, 0, playerEmpTime); if (empTime >= playerEmpTime * 9/10) { flightTime = 0; /* Just hit. Assume they'll get hit again */ } else { flightTime = MAX(0, flightTime - empTime); } } predict += Vector3i(iSinCosR(psDroid->sMove.moveDir, psDroid->sMove.speed*flightTime / GAME_TICKS_PER_SEC), 0); if (!isFlying(psDroid)) { predict.z = map_Height(removeZ(predict)); // Predict that the object will be on the ground. } } /* Fire off the bullet to the miss location. The miss is only visible if the player owns the target. (Why? - Per) */ // What bVisible really does is to make the projectile audible even if it misses you. Since the target is NULL, proj_SendProjectile can't check if it was fired at you. bool bVisibleAnyway = psTarget->player == selectedPlayer; // see if we were lucky to hit the target bool isHit = gameRand(100) <= resultHitChance; if (isHit) { /* Kerrrbaaang !!!!! a hit */ objTrace(psAttacker->id, "combFire: [%s]->%u: resultHitChance=%d, visibility=%d", psStats->pName, psTarget->id, resultHitChance, (int)psTarget->visible[psAttacker->player]); syncDebug("hit=(%d,%d,%d)", predict.x, predict.y, predict.z); } else /* Deal with a missed shot */ { const int minOffset = 5; int missDist = 2 * (100 - resultHitChance) + minOffset; Vector3i miss = Vector3i(iSinCosR(gameRand(DEG(360)), missDist), 0); predict += miss; psTarget = NULL; // Missed the target, so don't expect to hit it. objTrace(psAttacker->id, "combFire: Missed shot by (%4d,%4d)", miss.x, miss.y); syncDebug("miss=(%d,%d,%d)", predict.x, predict.y, predict.z); } // Make sure we don't pass any negative or out of bounds numbers to proj_SendProjectile CLIP(predict.x, 0, world_coord(mapWidth - 1)); CLIP(predict.y, 0, world_coord(mapHeight - 1)); proj_SendProjectileAngled(psWeap, psAttacker, psAttacker->player, predict, psTarget, bVisibleAnyway, weapon_slot, min_angle, fireTime); return true; }
bool survivesMine(eMonster m) { return isFlying(m); }
bool ignoresPlates(eMonster m) { return m == moMouse || isFlying(m); }
bool survivesChasm(eMonster m) { return isFlying(m); }
/** * Click on the map to pick up loot. We need the camera position to translate * screen coordinates to map locations. We need the hero position because * the hero has to be within range to pick up an item. */ ItemStack LootManager::checkPickup(Point mouse, Point cam, Point hero_pos, int &gold, bool inv_full) { Point p; SDL_Rect r; ItemStack loot_stack; gold = 0; loot_stack.item = 0; loot_stack.quantity = 0; // I'm starting at the end of the loot list so that more recently-dropped // loot is picked up first. If a player drops several loot in the same // location, picking it back up will work like a stack. for (int i=loot_count-1; i>=0; i--) { // loot close enough to pickup? if (abs(hero_pos.x - loot[i].pos.x) < LOOT_RANGE && abs(hero_pos.y - loot[i].pos.y) < LOOT_RANGE && !isFlying(i)) { p = map_to_screen(loot[i].pos.x, loot[i].pos.y, cam.x, cam.y); r.w = 32; r.h = 48; r.x = p.x - 16; r.y = p.y - 32; // clicked in pickup hotspot? if (mouse.x > r.x && mouse.x < r.x+r.w && mouse.y > r.y && mouse.y < r.y+r.h) { if (loot[i].stack.item > 0 && !inv_full) { loot_stack = loot[i].stack; removeLoot(i); return loot_stack; } else if (loot[i].stack.item > 0) { full_msg = true; } else if (loot[i].gold > 0) { gold = loot[i].gold; removeLoot(i); return loot_stack; } } } } return loot_stack; }
void ARDrone::trim() { if(!isFlying()) AT_FTRIM(); }
void ARDrone::calibrate() { if(isFlying()) AT_CALIB(); }
void LeprechaunController::dodgeRight() { if (!isCaneHit() && !isStoneHit() && !isFlying() && !isJumping() && !isDodgingLeft() && !isDodgingRight() && !isCarryingPig()) setBeginFlag(LeprechaunFlag::dodgingRight, true); }
void LeprechaunController::useItem(unsigned slot) { if (items[slot] == ItemType::none || isStoneHit() || isCaneHit() || isFlying()) return; switch(items[slot]) { case ItemType::explosionTrap: { setBeginFlag(LeprechaunFlag::explosionTrap, true); } break; case ItemType::attackDouble: { setBeginFlag(LeprechaunFlag::attackDouble, true); timers[TimerType::attackDouble] = configTimers[TimerType::attackDouble]; } break; case ItemType::invisibility: { if (isCarryingPig()) return; setBeginFlag(LeprechaunFlag::invisibility, true); timers[TimerType::invisibility] = configTimers[TimerType::invisibility]; } break; case ItemType::invulnerability: { setBeginFlag(LeprechaunFlag::invulnerability, true); timers[TimerType::invulnerability] = configTimers[TimerType::invulnerability]; } break; case ItemType::pigRobbery: { if (isCarryingPig()) return; setBeginFlag(LeprechaunFlag::pigRobbery, true); } break; case ItemType::showInvisibility: { setBeginFlag(LeprechaunFlag::showInvisibility, true); timers[TimerType::showInvisibility] = configTimers[TimerType::showInvisibility]; } break; case ItemType::speedBoost: { setBeginFlag(LeprechaunFlag::speedBoost, true); timers[TimerType::speedBoost] = configTimers[TimerType::speedBoost]; } break; } items[slot] = ItemType::none; usedItem = true; }