// ----------------------------------------------------------------------- // // // ROUTINE: CSoundSet::GetRandomFile() // // PURPOSE: Get a random sound from the set // // ----------------------------------------------------------------------- // const char* CSoundSet::GetRandomFile() { //if we're not set up or we have no files, bail if (!m_hRecord || !m_nTotalWeight || !m_vecWeights.size()) return ""; #if defined(PLATFORM_WIN32) || defined(PLATFORM_LINUX) HATTRIBUTE hFiles = g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sSoundFile); //only got one, return it if (m_vecWeights.size() == 1) return g_pLTDatabase->GetString(hFiles,0,""); uint32 nRand = GetRandom(0,m_nTotalWeight-1); for (uint32 n = 0; n < m_vecWeights.size(); ++n) { if (nRand < m_vecWeights[n]) return g_pLTDatabase->GetString(hFiles,n,""); } //if we got this far, just return the first value return g_pLTDatabase->GetString(hFiles,0,""); #endif // PLATFORM_WIN32 || PLATFORM_LINUX #ifdef PLATFORM_XENON HATTRIBUTE hCue = g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sXActCue); if (hCue) { return g_pLTDatabase->GetString(hCue,0,""); } else { return ""; } #endif // PLATFORM_XENON }
bool CMusicMgr::SetMood( Mood eMood ) { char szMusic[128]; uint32 iLevel = GetRandom(0, m_acMoods[eMood]-1); sprintf(szMusic, "MUSIC I %d measure", m_aanMoods[eMood][iLevel]); #ifndef _FINAL if ( g_ShowMusicTrack.GetFloat() > 0 ) { g_pLTServer->CPrint("Server sending client Music Message: (%s)", szMusic); } #endif HSTRING hMusic = g_pLTServer->CreateString(szMusic); CAutoMessage cMsg; cMsg.Writeuint8(MID_MUSIC); cMsg.WriteHString(hMusic); g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); FREE_HSTRING(hMusic); m_eLastMood = eMood; return true; }
// ----------------------------------------------------------------------- // // // ROUTINE: CSoundSet::GetRandomAltFile() // // PURPOSE: Get a random alternate sound from the set // // ----------------------------------------------------------------------- // const char* CSoundSet::GetRandomAltFile() { //if we're not set up or we have no files, bail if (!m_hRecord || !m_nAltTotalWeight || !m_vecAltWeights.size()) return ""; HATTRIBUTE hFiles = g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sAltSoundFile); //only got one, return it if (m_vecAltWeights.size() == 1) return g_pLTDatabase->GetString(hFiles,0,""); uint32 nRand = GetRandom(0,m_nAltTotalWeight-1); for (uint32 n = 0; n < m_vecAltWeights.size(); ++n) { if (nRand < m_vecAltWeights[n]) return g_pLTDatabase->GetString(hFiles,n,""); } //if we got this far, just return the first value return g_pLTDatabase->GetString(hFiles,0,""); }
// // Translate Exposure settings into a "current value". // LONGLONG CHardwareSimulation:: GetCurrentExposureTime() { PAGED_CODE(); ISP_FRAME_SETTINGS *pSettings = GetIspSettings(); LONGLONG Value = 0; LPCSTR Mode = "[UNKNOWN]"; if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO ) { // Get random value in global setting's bound (LONG) // I'm abandoning the reported min/max and using something more reasonable. Value = GetRandom( MIN_EXPOSURE_TIME*5, DEF_EXPOSURE_TIME*5 ); Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO"; } if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) { Value = pSettings->ExposureSetting.VideoProc.Value.ll; Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL"; } // Locked just reports the last value set... if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK ) { Value = m_LastReportedExposureTime; Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK"; } DBG_TRACE("ExposureMode=0x%016llX (%s), Time=%llu00ns, LastReported=%llu00ns", pSettings->ExposureMode, Mode, Value, m_LastReportedExposureTime ); m_LastReportedExposureTime = Value; return Value; }
SEARCH_SET::SearchObjectType SEARCH_SET::GetRandomSearchObjectType(float fJunkModifier) { if (fJunkModifier < 0.0f || fJunkModifier > 1.0f) { ASSERT(!"SEARCH_SET::GetRandomSearchObjectType(): bad skill modifier"); fJunkModifier = 1.0f; } //reduce the chance of random junk uint8 nJunkChance = (uint8)( (float)nItemPercent * fJunkModifier ); //figure out a new total uint8 nTotal = 100 - (nItemPercent - nJunkChance); //roll the die... uint8 nRandVal = GetRandom(1, nTotal); SearchObjectType eType = eUnknownObjectType; if (nRandVal <= nJunkChance) { eType = eItemObjectType; } else if (nRandVal <= nJunkChance + nAmmoPercent) { eType = eAmmoObjectType; } else if (nRandVal <= nJunkChance + nAmmoPercent + nWeaponPercent) { eType = eWeaponObjectType; } else { eType = eGearObjectType; } return eType; }
bool __CALLOUT InitializeShell() { Clear(BLUE); const char* str = "PRICE of HONOR!"; DrawTextString(40,60,str,Length(str),RED,BLUE); GetBatteryLevel(); SetScreenBrightness(100); char buff[200]; int res = snprintf(buff,sizeof(buff),"test %d",0); DrawPixel(1,1,WHITE); DoVibroAndBeep(500); ubyte_t l = GetLustraId(); SendRadioPacket(NULL,0); uword_t a = GetArmletId(); FILE log; OpenFile(&log, "log.txt", true); char* s = "log test"; WriteFile(&log, s, Length(s)); /* //int i = 0; //Color area[100]; //for (i=0; i<100; i++) area[i] = 0xF0F; //DrawArea(5,5,area,100,10,10); //WriteFile(&log, (char*)area, 100); //for (i=0; i<100; i++) area[i] = 0x0; //ReadFile(&log, (char*)area, 100); //AppendFile(&log, (char*)area, 100); //DrawArea(5,5,area,100,10,10); */ RequestTimer(TimerProc,100); int up = GetUpTime(); int rnd = GetRandom(50); //SetCureName is checked in AppMainThread //WritePill is checked in AppMainThread //StartThread(AppMainThread,NULL); return true; //TODO }
// // Translate ISO settings into a "current value". // ULONG CHardwareSimulation:: GetCurrentISOSpeed() { PAGED_CODE(); ISP_FRAME_SETTINGS *pSettings = GetIspSettings(); ULONG Value = 0; if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_AUTO ) { Value = GetRandom( (ULONG) 50, (ULONG) 3200 ); } else if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_MANUAL ) { Value = pSettings->ISOValue; } else { Value = // Try converting any legacy presets to a manual value. IsoPreset2Value( pSettings->ISOMode ); } return Value; }
void Reaction::DeepCopy(Reaction& other,BehaviorSet& behaviors) { desireValue = other.desireValue; desireType = other.desireType; for (size_t i = 0; i < other.affected.GetSize(); i++) { Behavior * behavior = behaviors.Find(other.affected[i]->GetName()); affected.Push(behavior); } eventType = other.eventType; range = other.range; factionDiff = other.factionDiff; oper = other.oper; weight = other.weight; values = other.values; valuesValid = other.valuesValid; randoms = other.randoms; randomsValid = other.randomsValid; type = other.type; activeOnly = other.activeOnly; inactiveOnly = other.inactiveOnly; reactWhenDead = other.reactWhenDead; reactWhenInvisible = other.reactWhenInvisible; reactWhenInvincible = other.reactWhenInvincible; onlyInterrupt = other.onlyInterrupt; doNotInterrupt = other.doNotInterrupt; // For now depend on that each npc do a deep copy to create its instance of the reaction for (uint ii=0; ii < values.GetSize(); ii++) { if (GetRandomValid((int)ii)) { values[ii] += psGetRandom(GetRandom((int)ii)); } } }
int main(int argc, char *argv[]) { FILE* fp; unsigned int i; struct data_t data; if (argc != 3) { printf("## Data Generator for 310_sort Ver.2013-10-13\n"); printf("## Usage: ./data_gen i random_seed\n"); printf("## : n = i * 1024n"); exit(1); } int random_seed = atoi(argv[2]); srand(random_seed); fp = fopen("310sort.txt", "wb"); if (fp==NULL) { fputs("fail to open\n", stderr); exit(1); } for (i=0; i<SIZE-1; i++){ data.buf[i] = GetRandom(); // printf("%d\n", data.buf[i]); } data.n = atoi(argv[1]) * 1024; //fwrite(&data, sizeof(unsigned int), SIZE, fp); for (i=0;i<SIZE-1; i++){ fprintf(fp, "%d,",data.buf[i]); } fprintf(fp, "%d,\n",data.n); fclose(fp); return 0; }
void CBaseParticleSystemFX::GetRandomColorInRange(DVector & vColor) { DFLOAT fColorR = GetRandom(m_vColor1.x, m_vColor2.x); // Kludge the color for software... if (m_bSetSoftwareColor) { m_pClientDE->SetSoftwarePSColor(m_hObject, m_vColor1.x/255.0f, m_vColor1.y/255.0f, m_vColor1.z/255.0f); } if (m_vColorRange.x <= 0.0f) { VEC_COPY(vColor, m_vColor1); } else { vColor.x = fColorR; vColor.y = (m_vColorRange.y * fColorR) / m_vColorRange.x; vColor.z = (m_vColorRange.z * fColorR) / m_vColorRange.x; } return; }
static void SampleSobol(cSamples *samples, cBounds *b, creal vol) { creal norm = vol*samples->weight; real *x = samples->x, *f = samples->f, *avg = samples->avg; ccount n = samples->n; count i, dim, comp; for( i = 0; i < n; ++i ) { GetRandom(x); for( dim = 0; dim < ndim_; ++x, ++dim ) *x = b[dim].lower + *x*(b[dim].upper - b[dim].lower); } DoSample(n, ndim_, samples->x, f); ResCopy(avg, f); f += ncomp_; for( i = 1; i < n; ++i ) for( comp = 0; comp < ncomp_; ++comp ) avg[comp] += *f++; for( comp = 0; comp < ncomp_; ++comp ) avg[comp] *= norm; }
void Bleed (edict_t *curse) { int take; edict_t *caster=curse->owner; if (curse->atype != BLEEDING) return; if (level.time < curse->wait) return; if (!G_ValidTarget(caster, curse->enemy, false)) { // remove the curse if the target dies que_removeent(curse->enemy->curses, curse, true); return; } // 33-99% health taken over duration of curse take = (curse->enemy->max_health * (0.033 * curse->monsterinfo.level)) / curse->monsterinfo.selected_time; //gi.dprintf("target %s take %d health %d/%d level %d time %.1f\n", // curse->enemy->classname, take, curse->enemy->health, curse->enemy->max_health, // curse->monsterinfo.level, curse->monsterinfo.selected_time); // damage limits if (take < 1) take = 1; if (take > 100) take = 100; T_Damage(curse->enemy, caster, caster, vec3_origin, vec3_origin, vec3_origin, take, 0, DAMAGE_NO_ABILITIES, MOD_LIFE_DRAIN); curse->wait = level.time + (GetRandom(3, 10) * FRAMETIME); }
int main(int argc, const char** argv) { const uint NUM_SHIPS = 50; const uint NUM_PLANETS = 500; const uint FIELD_DIMS = 500; GraphManager GraphManager; GraphManager.CreateGraph(NUM_PLANETS, { FIELD_DIMS, FIELD_DIMS }); GraphManager.FormEdges(); std::vector<Planet*> PlanetList; for (uint i = 0; i < GraphManager.NumNodes(); ++i) { Planet* p = new Planet(i, GraphManager.TakeNode()); PlanetList.push_back(p); } std::vector<Ship> ShipList; for (uint i = 0; i < NUM_SHIPS; ++i) { ShipList.emplace_back(i, PlanetList[GetRandom(0, NUM_PLANETS)], [&] (GraphNode* Start, GraphNode* End) { auto GraphList = GraphManager.FindPath(Start, End); std::vector<Planet*> Result; for(auto Node : GraphList) for (Planet* Planet : PlanetList) if (Planet->GetGraphNode() == Node) Result.push_back(Planet); return Result; }); } for (auto& Ship : ShipList) Ship.Tick(PlanetList); return 0; }
// Returns true if the AI has a valid flame pot position for this link, false // if it does not. // // Helper function for setting a flame pot position. If the AI already has // a valid position, it will use it. If the AI does not have a valid // position, a new position will be selected. static bool SelectFlamePotPosition( CAI* pAI, AINavMeshLinkAbstract* pLink ) { // Sanity checks. if ( !pAI || !pLink ) { return false; } // // Check to see if the AI already has a position. If he does, use it. // CAIWMFact queryExistingFact; queryExistingFact.SetFactType( kFact_Knowledge ); queryExistingFact.SetKnowledgeType( kKnowledge_FlamePotPosition ); queryExistingFact.SetSourceObject( pAI->GetAIBlackBoard()->GetBBTargetObject() ); queryExistingFact.SetTargetObject( pLink->GetHOBJECT() ); CAIWMFact* pCurrentPosition = pAI->GetAIWorkingMemory()->FindWMFact( queryExistingFact ); if ( NULL != pCurrentPosition ) { // Ignore the point if the AI is already very close to it; this is // likely an old position that was 'achieved'. LTVector vPosDelta2D = ( pAI->GetPosition() - pCurrentPosition->GetPos() ); vPosDelta2D.y = 0.0f; float flDistanceSqr2D = vPosDelta2D.MagSqr(); if ( flDistanceSqr2D >= g_flCirclingPositionAchievedDistSqr ) { return true; } } CAINavMeshPoly* pPoly = g_pAINavMesh->GetNMPoly( pLink->GetNMPolyID() ); if ( NULL == pPoly ) { return false; } // Get the total length of the edge, so we can pick a number within the // range [0, EdgeLength] int nEdges = pPoly->GetNumNMPolyEdges(); float flEdgeLengthSum = 0.0f; for ( int i = 0; i < nEdges; ++i ) { // Skip any edges which: // 1) Don't exist. // 2) Don't have polies on both sides. CAINavMeshEdge* pEdge = pPoly->GetNMPolyEdge( i ); if ( !pEdge || kNMPoly_Invalid == pEdge->GetNMPolyIDA() || kNMPoly_Invalid == pEdge->GetNMPolyIDB() ) { continue; } flEdgeLengthSum += ( pEdge->GetNMEdge0() - pEdge->GetNMEdge1() ).Mag(); // TODO: Don't need to get the mag here. } // Fail if there are no valid positions. float flRandomDistanceAlongEdge = GetRandom( 0.0f, flEdgeLengthSum ); if ( 0.0f == flRandomDistanceAlongEdge ) { return false; } // // Select a position on the edge. // bool bFoundPosition = false; LTVector vSelectedPosition; float flRemainingDistance = flRandomDistanceAlongEdge; for ( int i = 0; i < nEdges; ++i ) { // Skip any edges which: // 1) Don't exist. // 2) Don't have polies on both sides. CAINavMeshEdge* pEdge = pPoly->GetNMPolyEdge( i ); if ( !pEdge || kNMPoly_Invalid == pEdge->GetNMPolyIDA() || kNMPoly_Invalid == pEdge->GetNMPolyIDB() ) { continue; } float flEdgeLength = ( pEdge->GetNMEdge0() - pEdge->GetNMEdge1() ).Mag(); // TODO: Don't need to get the mag here. if ( flRemainingDistance < flEdgeLength ) { // Find the distance along the edge for the position. LTVector vEdgeDir = ( pEdge->GetNMEdge1() - pEdge->GetNMEdge0() ).GetUnit(); vSelectedPosition = pEdge->GetNMEdge0() + ( vEdgeDir * flRemainingDistance ); // Move the position 'out' of the link. If we don't do this, the AI may // end up standing in the flame pot link. If he does, the penalty // for pathing through the link does not apply. LTVector vNormalOutOfLink; pEdge->GetNMEdgeN( pPoly->GetNMPolyID(), &vNormalOutOfLink ); vNormalOutOfLink = -vNormalOutOfLink; vSelectedPosition += vNormalOutOfLink * 128.0f; bFoundPosition = true; break; } flRemainingDistance -= flEdgeLength; } if ( false == bFoundPosition ) { return false; } // // Remember the position and objects involved so that the satisfying // actions can use it, while validating that it is still valid. // CAIWMFact queryFact; queryFact.SetFactType( kFact_Knowledge ); queryFact.SetKnowledgeType( kKnowledge_FlamePotPosition ); CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindWMFact( queryExistingFact ); if ( !pFact ) { pFact = pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Knowledge ); if ( pFact ) { pFact->SetKnowledgeType( kKnowledge_FlamePotPosition ); } } if ( pFact ) { pFact->SetSourceObject( pAI->GetAIBlackBoard()->GetBBTargetObject() ); pFact->SetTargetObject( pLink->GetHOBJECT() ); pFact->SetPos( vSelectedPosition ); } return true; }
void CAIGoalCircleFlamePot::DeactivateGoal() { super::DeactivateGoal(); // If: // 1) The player is an enemy. // 2) There is another AI very close by // 3) That AI does not have a blitz task // ...this AI should blitz the player. This is an anti-clumping measure. HOBJECT hTarget = m_pAI->GetAIBlackBoard()->GetBBTargetObject(); bool bShouldBlitz = false; if ( m_pAI->HasTarget( kTarget_Character ) && IsPlayer( hTarget ) ) { CAI::AIList::const_iterator itEachAI = CAI::GetAIList().begin(); CAI::AIList::const_iterator itLastAI = CAI::GetAIList().end(); for ( ; itEachAI != itLastAI; ++itEachAI ) { CAI* pCurrentAI = *itEachAI; // Ignore NULL, self and dead AI. if ( NULL == pCurrentAI || pCurrentAI == m_pAI || IsDeadAI( pCurrentAI->GetHOBJECT() ) ) { continue; } // Ignore AIs who are far away in 2D (false positives are okay). LTVector vDelta2D = ( pCurrentAI->GetPosition() - m_pAI->GetPosition() ); vDelta2D.y = 0.0f; if ( vDelta2D.MagSqr() > g_flTooCloseToEnemySqr ) { continue; } // Ignore AI who are already blitzing. CAIWMFact factQuery; factQuery.SetFactType( kFact_Task ); factQuery.SetTaskType( kTask_BlitzCharacter ); if ( pCurrentAI->GetAIWorkingMemory()->FindWMFact( factQuery ) ) { continue; } // AI should blitz. bShouldBlitz = true; break; } } if ( bShouldBlitz || ( 0 == GetRandom( 0, 2 ) ) ) { CAIWMFact factQuery; factQuery.SetFactType( kFact_Task ); factQuery.SetTaskType( kTask_BlitzCharacter ); CAIWMFact* pFact = m_pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Task ); if ( pFact ) { pFact->SetTaskType( kTask_BlitzCharacter ); pFact->SetTargetObject( hTarget ); pFact->SetIndex( kContext_None ); pFact->SetFactFlags( kFactFlag_Scripted, 1.f ); } } }
DBOOL CShellCasingFX::Update() { if (!m_hObject || !m_pClientDE) return DFALSE; if (m_pClientDE->GetTime() > m_fExpireTime) return DFALSE; if (m_bInVisible) { m_bInVisible = DFALSE; m_pClientDE->SetObjectFlags(m_hObject, FLAG_VISIBLE); } if (m_bResting) return DTRUE; DRotation rRot; // If velocity slows enough, and we're on the ground, just stop bouncing and just wait to expire. if (m_movingObj.m_PhysicsFlags & MO_RESTING) { m_bResting = DTRUE; // Stop the spinning... m_pClientDE->SetupEuler(&rRot, 0, m_fYaw, 0); m_pClientDE->SetObjectRotation(m_hObject, &rRot); /* // Shell is at rest, we can add a check here to see if we really want // to keep it around depending on detail settings... HLOCALOBJ hObjs[1]; DDWORD nNumFound, nBogus; m_pClientDE->FindObjectsInSphere(&m_movingObj.m_Pos, 64.0f, hObjs, 1, &nBogus, &nNumFound); // Remove thyself... if (nNumFound > 15) return DFALSE; */ } else { if (m_fPitchVel != 0 || m_fYawVel != 0) { DFLOAT fDeltaTime = m_pClientDE->GetFrameTime(); m_fPitch += m_fPitchVel * fDeltaTime; m_fYaw += m_fYawVel * fDeltaTime; m_pClientDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f); m_pClientDE->SetObjectRotation(m_hObject, &rRot); } } DVector vNewPos; if (UpdateMovingObject(DNULL, &m_movingObj, &vNewPos)) { ClientIntersectInfo info; SurfaceType eType = SURFTYPE_UNKNOWN; if (BounceMovingObject(DNULL, &m_movingObj, &vNewPos, &info, &eType)) { if (m_nBounceCount > 0) { char sType[10]; char sFile[MAX_CS_FILENAME_LEN]; switch(eType) { // case SURFTYPE_FLESH: _mbscpy((unsigned char*)sType, (const unsigned char*)"Flesh"); break; case SURFTYPE_GLASS: _mbscpy((unsigned char*)sType, (const unsigned char*)"Glass"); break; case SURFTYPE_METAL: _mbscpy((unsigned char*)sType, (const unsigned char*)"Metal"); break; case SURFTYPE_PLASTIC: _mbscpy((unsigned char*)sType, (const unsigned char*)"Plastic"); break; case SURFTYPE_TERRAIN: _mbscpy((unsigned char*)sType, (const unsigned char*)"Terrain"); break; case SURFTYPE_LIQUID: _mbscpy((unsigned char*)sType, (const unsigned char*)"Water"); break; case SURFTYPE_WOOD: _mbscpy((unsigned char*)sType, (const unsigned char*)"Wood"); break; case SURFTYPE_STONE: default: _mbscpy((unsigned char*)sType, (const unsigned char*)"Stone"); break; } sprintf(sFile, "Sounds\\Weapons\\ShellDrops\\%s\\Shell%d.wav", sType, GetRandom(1, 2)); PlaySoundFromPos(&vNewPos, sFile, 150.0f, SOUNDPRIORITY_MISC_LOW); } // Adjust the bouncing.. m_fPitchVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_fYawVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_nBounceCount--; if (m_nBounceCount <= 0) { m_movingObj.m_PhysicsFlags |= MO_RESTING; } } VEC_COPY(m_movingObj.m_Pos, vNewPos); if (m_pClientDE->GetPointStatus(&vNewPos) == DE_OUTSIDE) { return DFALSE; } m_pClientDE->SetObjectPos(m_hObject, &vNewPos); } return DTRUE; }
void Player::FireWeapon() { SPADES_MARK_FUNCTION(); Vector3 muzzle = GetEye(); muzzle += GetFront() * 0.01f; // for hit-test debugging std::map<int, HitTestDebugger::PlayerHit> playerHits; std::vector<Vector3> bulletVectors; //Vector3 right = GetRight(); //Vector3 up = GetUp(); int pellets = weapon->GetPelletSize(); float spread = weapon->GetSpread(); GameMap *map = world->GetMap(); // pyspades takes destroying more than one block as a // speed hack (shotgun does this) bool blockDestroyed = false; Vector3 dir2 = GetFront(); for(int i =0 ; i < pellets; i++){ // AoS 0.75's way (dir2 shouldn't be normalized!) dir2.x += (GetRandom() - GetRandom()) * spread; dir2.y += (GetRandom() - GetRandom()) * spread; dir2.z += (GetRandom() - GetRandom()) * spread; Vector3 dir = dir2.Normalize(); bulletVectors.push_back(dir); // first do map raycast GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 500); Player *hitPlayer = NULL; float hitPlayerDistance = 0.f; HitBodyPart hitPart = HitBodyPart::None; for(int i = 0; i < world->GetNumPlayerSlots(); i++){ Player *other = world->GetPlayer(i); if(other == this || other == NULL) continue; if(other == this || !other->IsAlive() || other->GetTeamId() >= 2) continue; // quickly reject players unlikely to be hit if(!other->RayCastApprox(muzzle, dir)) continue; HitBoxes hb = other->GetHitBoxes(); Vector3 hitPos; if(hb.head.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Head; } } if(hb.torso.RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; hitPart = HitBodyPart::Torso; } } for(int j = 0; j < 3 ;j++){ if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) { float dist = (hitPos - muzzle).GetLength(); if(hitPlayer == NULL || dist < hitPlayerDistance){ hitPlayer = other; hitPlayerDistance = dist; switch(j) { case 0: hitPart = HitBodyPart::Limb1; break; case 1: hitPart = HitBodyPart::Limb2; break; case 2: hitPart = HitBodyPart::Arms; break; } } } } } Vector3 finalHitPos; finalHitPos = muzzle + dir * 128.f; if(hitPlayer == nullptr && !mapResult.hit) { // might hit water surface. } if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f && (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){ IntVector3 outBlockCoord = mapResult.hitBlock; // TODO: set correct ray distance // FIXME: why ray casting twice? finalHitPos = mapResult.hitPos; if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 && outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()){ if(outBlockCoord.z == 63) { if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else if(outBlockCoord.z == 62) { // blocks at this level cannot be damaged if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); }else{ int x = outBlockCoord.x; int y = outBlockCoord.y; int z = outBlockCoord.z; SPAssert(map->IsSolid(x, y, z)); Vector3 blockF = {x + .5f, y + .5f, z + .5f}; float distance = (blockF - muzzle).GetLength(); uint32_t color = map->GetColor(x, y, z); int health = color >> 24; health -= weapon->GetDamage(HitTypeBlock, distance); if(health <= 0 && !blockDestroyed){ health = 0; blockDestroyed = true; //send destroy cmd if(world->GetListener() && world->GetLocalPlayer() == this) world->GetListener()->LocalPlayerBlockAction (outBlockCoord, BlockActionTool); } color = (color & 0xffffff) | ((uint32_t)health << 24); if(map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); if(world->GetListener()) world->GetListener()->BulletHitBlock(mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } }else if(hitPlayer != NULL){
void Color::SetRandom(){ SetValor(GetRandom(0,6)); }
void p_medic_reanimate (edict_t *ent, edict_t *target) { int skill_level; vec3_t bmin, bmax; edict_t *e; skill_level = floattoint((1.0+MEDIC_RESURRECT_BONUS)*ent->myskills.abilities[MEDIC].current_level); if (!strcmp(target->classname, "drone") && (ent->num_monsters + target->monsterinfo.control_cost <= MAX_MONSTERS)) { target->monsterinfo.level = skill_level; M_SetBoundingBox(target->mtype, bmin, bmax); if (G_IsValidLocation(target, target->s.origin, bmin, bmax) && M_Initialize(ent, target)) { // restore this drone target->monsterinfo.slots_freed = false; // reset freed flag target->health = 0.33*target->max_health; target->monsterinfo.power_armor_power = 0.33*target->monsterinfo.max_armor; target->monsterinfo.resurrected_time = level.time + 2.0; target->activator = ent; // transfer ownership! target->nextthink = level.time + MEDIC_RESURRECT_DELAY; gi.linkentity(target); target->monsterinfo.stand(target); ent->num_monsters += target->monsterinfo.control_cost; safe_cprintf(ent, PRINT_HIGH, "Resurrected a %s. (%d/%d)\n", target->classname, ent->num_monsters, MAX_MONSTERS); } } else if ((!strcmp(target->classname, "bodyque") || !strcmp(target->classname, "player")) && (ent->num_monsters + 1 <= MAX_MONSTERS)) { int random=GetRandom(1, 3); vec3_t start; e = G_Spawn(); VectorCopy(target->s.origin, start); // kill the corpse T_Damage(target, target, target, vec3_origin, target->s.origin, vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, 0); //4.2 random soldier type with different weapons if (random == 1) { // blaster e->mtype = M_SOLDIER; e->s.skinnum = 0; } else if (random == 2) { // rocket e->mtype = M_SOLDIERLT; e->s.skinnum = 4; } else { // shotgun e->mtype = M_SOLDIERSS; e->s.skinnum = 2; } e->activator = ent; e->monsterinfo.level = skill_level; M_Initialize(ent, e); e->health = 0.2*e->max_health; e->monsterinfo.power_armor_power = 0.2*e->monsterinfo.max_armor; e->s.skinnum |= 1; // injured skin e->monsterinfo.stand(e); if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { start[2] += 24; if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { G_FreeEdict(e); return; } } VectorCopy(start, e->s.origin); gi.linkentity(e); e->nextthink = level.time + MEDIC_RESURRECT_DELAY; ent->num_monsters += e->monsterinfo.control_cost; safe_cprintf(ent, PRINT_HIGH, "Resurrected a soldier. (%d/%d)\n", ent->num_monsters, MAX_MONSTERS); } else if (!strcmp(target->classname, "spiker") && ent->num_spikers + 1 <= SPIKER_MAX_COUNT) { e = CreateSpiker(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_spikers--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 4; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } else if (!strcmp(target->classname, "obstacle") && ent->num_obstacle + 1 <= OBSTACLE_MAX_COUNT) { e = CreateObstacle(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_obstacle--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 6; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } else if (!strcmp(target->classname, "gasser") && ent->num_gasser + 1 <= GASSER_MAX_COUNT) { e = CreateGasser(ent, skill_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_gasser--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = 0.33 * e->max_health; e->s.frame = 0; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); } }
void ProcDropItemAfterBattle(CNPC* df, CPC* opc, CPC* tpc, int level) { if(df->m_pZone->IsComboZone()) { DropComboGiftMob(df, opc, tpc, level); return ; } #ifdef SYSTEM_TREASURE_MAP if( df->m_idNum == TREASURE_BOX_NPC_INDEX ) // npc 일경우 보물 상자만 드랍 한다. { DropTreasureBoxNpc(df, opc, tpc, level); return; } // 보물 지도는 필드에서만 드랍된다. if( df->m_pZone->CheckTreasureDropFlag() && df->m_pZone->IsFieldZone() ) { DropTreasureMap(df, opc, tpc, level); } #endif // 아이템 드롭율 증폭제 검사 bool hcSepDrop = false; bool hcDropPlus_S360 = false; bool hcPlatinumDrop = false; if (opc && tpc == opc) { if (opc->m_assist.m_avAddition.hcSepDrop) { opc->m_assist.CureByItemIndex(884); // 아이템 hcSepDrop = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP); SEND_Q(rmsg, opc->m_desc); } if (opc->m_assist.m_avAddition.hcSepDrop_Cash) { opc->m_assist.CureByItemIndex(6096); // 아이템 hcSepDrop = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP); SEND_Q(rmsg, opc->m_desc); } // 추천서버포션 드롭율 상승 else if (opc->m_assist.m_avAddition.hcDropPlus_S360) { opc->m_assist.CureBySkillIndex(360); hcDropPlus_S360 = true; } else if(opc->m_assist.m_avAddition.hcPlatinumDrop) { opc->m_assist.CureByItemIndex(2855); // 아이템 hcPlatinumDrop = true; } } // 아이템 드롭율 증폭제 검사 // 아이템 드롭 int loopcount; bool IsNotDropInCube = true; #ifdef EXTREME_CUBE if(df->m_bCubeRegen) IsNotDropInCube = false; #endif // EXTREME_CUBE] int itemDropLoop = MAX_NPC_DROPITEM_LOOP; #ifdef EVENT_WORLDCUP_2010 if( df->m_proto->m_index == 1105 ) itemDropLoop = 1; #endif // #ifdef EVENT_WORLDCUP_2010 for (loopcount = 0; loopcount < itemDropLoop; loopcount++) { // 5레벨보다 크면 아이템 드롭 없음 // 1. 드롭할 수 있는 수 범위에서 아이템 선정 // 2. 그 아이팀의 드롭확률로 드롭여부 결정 // 3. 드롭 #ifdef EVENT_WORLDCUP_2010 // 트라이앵글 볼(1105) 일경우 무조건 아이템을 드랍 한다 if( ( df->m_proto->m_itemCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) || df->m_proto->m_index == 1105) #else if (df->m_proto->m_itemCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) #endif { CItem* dropItem = NULL; int tableindex; #ifdef EVENT_WORLDCUP_2010 if( df->m_proto->m_index == 1105 ) { // npc툴 드랍 테이블1,2번에 각각 축국공, 황금 축구공이 100%g확률로 들어가 있어야 한다. tableindex = GetRandom(1, 10000); // 0. 95%확률로 축구공. 1. 5% 확률 황금 축구공 2. 꽝 if( tableindex <= 9000 ) tableindex = 0; else if( tableindex <= 9500) tableindex = 1; else tableindex = 2; } else #endif tableindex = GetRandom(0, MAX_NPC_DROPITEM - 1); int dropprob = df->m_proto->m_itemPercent[tableindex]; dropprob = dropprob * gserver->m_itemDropProb / 100; if (tpc) { // 자두 if (tpc->m_assist.m_avAddition.hcDropPlus_838) dropprob *= 2; // 행운의스크롤, 5080강운의 스크롤과 변수를 같이 사용한다. if (tpc->m_assist.m_avAddition.hcScrollDrop) dropprob *= 2; if (tpc->m_assist.m_avAddition.hcScrollDrop_5081) dropprob *= 4; // 행운 주문서 if (tpc->m_assist.m_avAddition.hcDropPlus_2141) { if (GetRandom(1, 10000) <= 2000 ) // 20 % { dropprob *= 2; } } // 플래티늄 행운의 스크롤 if(tpc->m_assist.m_avAddition.hcPlatinumScroll) { dropprob *= 4; } } // BS 수정 : 아이템 드롭 이벤트 dropprob = dropprob * gserver->m_nItemDropEventRate / 100; // 드롭율 상승 %단위 누적 if (opc && tpc == opc && opc->m_assist.m_avAddition.hcDropPlusPer100 > 0) dropprob += dropprob * opc->m_assist.m_avAddition.hcDropPlusPer100 / 100; #ifdef DOUBLE_ITEM_DROP if ( gserver->m_bDoubleItemEvent ) dropprob += dropprob * gserver->m_bDoubleItemPercent / 100; #endif // DOUBLE_ITEM_DROP // 9월 이벤트 드롭율 10배 if (hcSepDrop) dropprob = dropprob * 10; // 추천서버포션 드롭율 상승 else if (hcDropPlus_S360) dropprob = dropprob * 10; else if (hcPlatinumDrop) dropprob = dropprob * 20; if( opc && opc->m_assist.m_avAddition.hcRandomDropUp > 0 && GetRandom(0,100) <= opc->m_assist.m_avAddition.hcRandomDropUp ) { dropprob = dropprob * 10; CNetMsg::SP rmsg(new CNetMsg); EffectEtcMsg(rmsg, opc, MSG_EFFECT_ETC_RANDOM_DROP); opc->m_pArea->SendToCell(rmsg, opc, true); } if( tpc ) { if( gserver->isActiveEvent( A_EVENT_XMAS) ) { if ( tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007 > 0) dropprob += df->m_proto->m_itemPercent[tableindex] * tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007; } } #ifdef IMP_SPEED_SERVER // Zone Drop 률 적용 if( gserver->m_bSpeedServer && tpc && tpc->m_pZone ) { dropprob = dropprob * tpc->m_pZone->GetZoneDrop() / 100; } #endif //IMP_SPEED_SERVER if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) { if (df->m_proto->m_item[tableindex] == 84) { dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, df->m_level, 1); } #if defined (LC_USA) || defined(LC_BILA) // 대만과 말레이시아는 중소형 체력약이 소형으로 떨어진다 else if( df->m_proto->m_item[tableindex] == 44 || df->m_proto->m_item[tableindex] == 45 ) { dropItem = df->m_pArea->DropItem(43, df, 0, 0, 1); } // 대만과 말레이시아는 중형 마나 회복 물약이 드롭되지 않는다. else if ( df->m_proto->m_item[tableindex] == 485 ) { dropItem = NULL; } #endif // #if defined (LC_USA) || defined(LC_BILA) #if defined (LC_USA) || defined(LC_BILA) // 대형 힐링포션 제작서, 대형 마나, 중형 마나 메뉴얼 드롭 금지 else if ( df->m_proto->m_item[tableindex] == 1066 || df->m_proto->m_item[tableindex] == 1067 || df->m_proto->m_item[tableindex] == 1068 || df->m_proto->m_item[tableindex] == 489) { dropItem = NULL; } #endif // #if defined (LC_USA) || defined (LC_BILA) else { // 61레벨 무기류 및 65레벨 방어구 드롭 금지 제작서 드롭 금지 switch (df->m_proto->m_item[tableindex]) { case -1: // 지우지 말것 dropItem = NULL; break; default: { bool bAvailableDrop = true; if (bAvailableDrop) dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, 0, 1, true); else dropItem = NULL; } break; } // switch (df->m_proto->m_item[tableindex]) } } // if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) if (dropItem) { // 050303 : bs : 몬스터에게서 plus 붙은 아이템 만들기 if (df->m_proto->m_minplus >= 0 && df->m_proto->m_maxplus >= df->m_proto->m_minplus && df->m_proto->m_probplus > 0 && dropItem->CanUpgrade()) { if (GetRandom(1, 10000) <= df->m_proto->m_probplus) { dropItem->setPlus(GetRandom(df->m_proto->m_minplus, df->m_proto->m_maxplus)); } } // Drop Msg 보내기 // 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려) if (tpc) dropItem->m_preferenceIndex = tpc->m_index; else dropItem->m_preferenceIndex = -1; { CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ); } if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS)) { GAMELOG << init("MOB DROP ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } } // // 아이템 드롭 // opc 공격 캐릭터, tpc 우선권 캐릭터 int job = -1; if(tpc) job = (int)tpc->m_job; else if(opc) job = (int)opc->m_job; if(job >= 0 && job < JOBCOUNT) { if(level != -1 && level - df->m_level <= 5) { if(df->m_proto->m_jobdropitem[job] > 0 && df->m_proto->m_jobdropitemprob[job] > 0) { int dropprob = df->m_proto->m_jobdropitemprob[job]; if(GetRandom(1, 10000) <= dropprob) { CItem* dropItem = NULL; dropItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_jobdropitem[job], -1, 0, 0, 1); if(dropItem) { df->m_pArea->DropItem(dropItem, df); CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, df, true); GAMELOG << init("MOB DROP ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } } } // 이 아이템은 레벨제한 없이 무조건 떨어트린다. int loopi = 0; for(loopi = 0; loopi < MAX_NPC_DROPITEM; loopi++) { if(df->m_proto->m_dropallitem[loopi] < 1) continue ; int dropprob = df->m_proto->m_dropallitemprob[loopi]; if(GetRandom(1, 10000) <= dropprob) { CItem* pItem = NULL; pItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_dropallitem[loopi], -1, 0, 0, 1); if(pItem) { if (tpc) pItem->m_preferenceIndex = tpc->m_index; else pItem->m_preferenceIndex = -1; df->m_pArea->DropItem(pItem, df); CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, pItem); df->m_pArea->SendToCell(rmsg, df, true); GAMELOG << init("MOB DROP ALL ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(pItem) << end; } } } // 보석 드롭 for (loopcount = 0; loopcount < MAX_NPC_DROPITEM_LOOP; loopcount++) { // 5레벨보다 크면 아이템 드롭 없음 // 1. 드롭할 수 있는 수 범위에서 아이템 선정 // 2. 그 아이팀의 드롭확률로 드롭여부 결정 // 3. 드롭 if (df->m_proto->m_jewelCount > 0 && ((level != -1 && level - df->m_level <= 5) || !IsNotDropInCube) ) { CItem* dropItem = NULL; int tableindex = GetRandom(0, MAX_NPC_DROPJEWEL - 1); int dropprob = df->m_proto->m_jewelPercent[tableindex]; if (df->m_proto->m_jewel[tableindex] != -1 && GetRandom(1, 10000) <= dropprob) { switch (df->m_proto->m_jewel[tableindex]) { case -1: // 지우지 말것 dropItem = NULL; break; default: { dropItem = df->m_pArea->DropItem(df->m_proto->m_jewel[tableindex], df, 0, 0, 1, true); } break; } } if (dropItem) { // Drop Msg 보내기 // 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려) if (tpc) dropItem->m_preferenceIndex = tpc->m_index; else dropItem->m_preferenceIndex = -1; { CNetMsg::SP rmsg(new CNetMsg); ItemDropMsg(rmsg, df, dropItem); df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ); } GAMELOG << init("JEWEL ITEM") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "ITEM" << delim << itemlog(dropItem) << end; } } } // 보석 드롭 // typedef void (*NPC_DROP_FUNCTION) (CNPC* npc, CPC* pc, CPC* tpc, int level); // pc, tpc는 NULL이 될 수 있다 NPC_DROP_FUNCTION fnNPCDrop[] = { DropBloodGem, // 블러드젬 드롭 : 대만 천하대란 DropLuckySpecialStone, // 행운의 제련석 드롭 : 대만 천하대란 DropSpecialRefineStone, // 고제 드롭 DropPersonalDungeon2Ticket, // 퍼스널던전 2 입장권 드롭 DropBoosterItem, // 부스터 DropPersonalDungeon3Ticket, // 퍼스널던전 3 입장권 드롭 DropPersonalDungeon4Ticket, // 퍼스널던전 4 입장권 드롭 DropPetEgg, // 애완동물 알 드롭 DropNewMoonStoneItem, #ifdef EVENT_VALENTINE DropValentineItem, // 발렌타인 #endif #ifdef EVENT_WHITEDAY DropWhiteDayItem, // 화이트데이 #endif #ifdef DROP_MAKE_DOCUMENT DropMakeDocument, // 제작문서 드롭 #endif // DROP_MAKE_DOCUMENT DropRecommendItem, // 추천 서버 전용 인스턴스 포션 아이템 DropGoldenBallItem, // 골든볼 이벤트 RegenBlessWarrior, // 전사의 축복 DropHalloween2006Item, // 2006 할로윈 이벤트 DropRaidMonsterItem, DropMobScrollSpecialStone, DropEventGomdori2007, DropEventIndependenceDay2007USA, DropEventAprilFoolEvent, #ifdef EVENT_DROPITEM DropEventNpcDropItem, #endif // EVENT_DROPITEM DropAPetLifeBook, DropPhoenix_MembersTicket, DropTriggerItem, #ifdef LACARETTE_SYSTEM DropLacaRette, #endif DropHolyWater, DropWorldCupEvent, DropHalloween2014Event, DropArtifactItem, #ifdef DEV_EVENT_AUTO DropEventItem, #endif // DEV_EVENT_AUTO }; // 드롭 함수 테이블 // 방어코드 : tpc가 있는데 m_pZone이나 m_pArea가 없으면 NULL로 바꾼다 if (tpc && (tpc->m_pZone == NULL || tpc->m_pArea == NULL)) tpc = NULL; unsigned int fnDropLoop; for (fnDropLoop = 0; fnDropLoop < sizeof(fnNPCDrop) / sizeof(NPC_DROP_FUNCTION); fnDropLoop++) (fnNPCDrop[fnDropLoop])(df, opc, tpc, level); gserver->doEventDropItem(df, opc, tpc); // 돈 떨어뜨릴 확률 : default 80 % // BS 수정 : 낮은 레벨 몬스터 잡을때 패널티만 존재 // 잠수함 : 돈 드롭확률 int moneyDropProb = MONEY_DROP_PROB * gserver->m_moneyDropProb / 100; if (level != -1 && df->m_level - level < 0) moneyDropProb += (df->m_level - level) * 500; bool hcSepNas = false; if (opc && tpc == opc) { if (opc->m_assist.m_avAddition.hcSepNas) { opc->m_assist.CureByItemIndex(885); // 나스 hcSepNas = true; CNetMsg::SP rmsg(new CNetMsg); EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_NAS); SEND_Q(rmsg, opc->m_desc); } } // 돈 드롭 //CItem* money = NULL; if (GetRandom(1, 10000) <= moneyDropProb) // 80% { // 돈 액수 : +- 50% if(!df) { //잘못된 위치에서 몬스터를 잡았을 경우 GAMELOG << "NOT FOUND TARGET....." << df->m_idNum << end; return ; } GoldType_t count = df->m_proto->m_price * GetRandom(50, 150) / 100; #ifdef LC_RUS // 러시아는 망각의 신전을 제외한 지역에서 65 레벨 이상의 몬스터가 떨구는 나스는 40% 로 줄인다. if (df->m_pZone && df->m_pZone->m_index != ZONE_DUNGEON4 && df->m_level >= 65) count = count / 5 * 2; #endif // LC_RUS // 더블이벤트 if (gserver->m_bDoubleEvent) { #ifdef NEW_DOUBLE_GM_ZONE if( gserver->m_bDoubleEventZone == -1 || gserver->m_bDoubleEventZone == df->m_pZone->m_index ) #endif // NEW_DOUBLE_GM_ZONE count = count * gserver->m_bDoubleNasPercent / 100 ; } // 9월 이벤트 나스 10배 if (hcSepNas) count = count * 10; // 행운 주문서 if (tpc && tpc->m_assist.m_avAddition.hcDropPlus_2141) { if (GetRandom(1, 10000) <= 8000 ) // 80 % { count *= 2; } } //#endif // CAHNCE_EVENT if( opc && opc->m_pZone->m_index == ZONE_DRATAN_CASTLE_DUNGEON ) { CDratanCastle * pCastle = CDratanCastle::CreateInstance(); if( opc->m_guildInfo && opc->m_guildInfo->guild()->index() == pCastle->GetOwnerGuildIndex() ) { // 세금 없음 } else { GoldType_t tax=0; tax = count * pCastle->m_dvd.GetHuntRate() / 100; count = count - tax; gserver->AddTaxItemDratan( tax ); } } if( tpc == NULL ) { GAMELOG << "NOT FOUND TARGET....." << end; return; } //파티이면서 타입이 균등일때 if (tpc->IsParty() && (tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_RANDOM || tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_BATTLE) ) { DivisionPartyMoney(tpc, count); } //원정대이면서 타입이 균등일때 else if ( tpc->IsExped() && (tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_RANDOM || tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_BATTLE) ) { DivisionExpedMoney(tpc, count); } //이도 저도 아닐때 (개인 플레이할때) else { int bonus = 0; if(tpc->m_avPassiveAddition.money_nas > 0) { bonus += tpc->m_avPassiveAddition.money_nas; } if(tpc->m_avPassiveRate.money_nas > 0) { bonus = count * (tpc->m_avPassiveRate.money_nas - 100) / SKILL_RATE_UNIT; } count = count + count * tpc->m_artiGold / 100; tpc->m_inventory.increaseMoney(count, bonus); } if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS)) { GAMELOG << init("MOB DROP MONEY") << "NPC INDEX" << delim << df->m_proto->m_index << delim << "NPC NAME" << delim << df->m_name << delim << "MONEY(NAS)" << delim << count << end; } } }
LTBOOL CLineSystemFX::Update() { if (!m_hObject || !m_pClientDE || m_bWantRemove) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); // Hide/show the line system if necessary... if (m_hServerObject) { uint32 dwUserFlags; g_pCommonLT->GetObjectFlags(m_hServerObject, OFT_User, dwUserFlags); if (!(dwUserFlags & USRFLG_VISIBLE)) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE); m_fLastTime = fTime; return LTTRUE; } else { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE); } } // Debugging aid... if (s_cvarTweak.GetFloat() > 0) { TweakSystem(); } if (m_bFirstUpdate) { m_fLastTime = fTime; m_bFirstUpdate = LTFALSE; } else { UpdateSystem(); } // Make sure it is time to update... if (fTime < m_fLastTime + m_fNextUpdate) { return LTTRUE; } // Ok, how many to add this frame.... float fTimeDelta = fTime - m_fLastTime; // Make sure delta time is no less than 15 frames/sec if we're // continuously adding lines... if (m_bContinuous) { fTimeDelta = fTimeDelta > 0.0666f ? 0.0666f : fTimeDelta; } int nToAdd = (int) floor(m_cs.fLinesPerSecond * fTimeDelta); nToAdd = LTMIN(nToAdd, (int)(MAX_LINES_PER_SECOND * fTimeDelta)); // Add new lines... AddLines(nToAdd); // Determine when next update should occur... if (m_cs.fBurstWait > 0.001f) { m_fNextUpdate = m_cs.fBurstWait * GetRandom(m_cs.fBurstWaitMin, m_cs.fBurstWaitMax); } else { m_fNextUpdate = 0.001f; } m_fLastTime = fTime; return LTTRUE; }
// 믈리 어택 void do_pd_Attack(CPC* pc, CNetMsg::SP& msg) { CDratanCastle * pCastle = CDratanCastle::CreateInstance(); pCastle->CheckRespond(pc); RequestClient::doPDAttack* packet = reinterpret_cast<RequestClient::doPDAttack*>(msg->m_buf); if (packet->multicount > 20) { LOG_ERROR("HACKING : invalid multi count[%d]. charIndex[%d]", packet->multicount, pc->m_index); pc->m_desc->Close("invalid multi count"); return; } // multi target의 중복 검사 if (packet->multicount > 1) { std::set<int> tset; for (int i = 0; i < packet->multicount; ++i) { if (tset.insert(packet->list[i].index).second == false) { LOG_ERROR("HACKING : duplicate multi target[%d]. charIndex[%d]", packet->list[i].index, pc->m_index); pc->m_desc->Close("duplicate multi target"); return; } } } // 대상 검색 : 인접 셀에서만 CArea* area = pc->m_pArea; if (area == NULL) { LOG_ERROR("HACKING : not found area. charIndex[%d]", pc->m_index); pc->m_desc->Close("not found area"); return; } CCharacter* tch = area->FindCharInCell(pc, packet->tIndex, (MSG_CHAR_TYPE)packet->tCharType); if (tch == NULL) return; int preIndex = -1; for (int i = 0; i < packet->multicount; ++i) { if(preIndex == packet->list[i].index) { // 가까운 마을로 int nearZone; int nearZonePos; CZone* pZone = gserver->FindNearestZone(pc->m_pZone->m_index, GET_X(pc), GET_Z(pc), &nearZone, &nearZonePos); if (pZone == NULL) return; GoZone(pc, nearZone, pZone->m_zonePos[nearZonePos][0], // ylayer GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f, // x GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f); // z return; } preIndex = packet->list[i].index; CCharacter* ch = area->FindCharInCell(pc, packet->list[i].index, (MSG_CHAR_TYPE) MSG_CHAR_NPC); if(!ch) continue; if( !IS_NPC(ch) ) { CPC* bugPC = NULL; if( IS_ELEMENTAL(ch) ) { CElemental *ele = TO_ELEMENTAL(ch); bugPC = ele->GetOwner(); } if( IS_PET(ch) ) { CPet* pet = TO_PET(ch); bugPC = pet->GetOwner(); } if( IS_PC(ch) ) { bugPC = TO_PC(ch); } if( !bugPC ) return; // 가까운 마을로 int nearZone; int nearZonePos; CZone* pZone = gserver->FindNearestZone(bugPC->m_pZone->m_index, GET_X(bugPC), GET_Z(bugPC), &nearZone, &nearZonePos); if (pZone == NULL) return; GoZone(bugPC, nearZone, pZone->m_zonePos[nearZonePos][0], // ylayer GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f, // x GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f); // z GAMELOG << init("PD_BUG", bugPC) << end; return; } int ret = ProcAttack(ch, tch, ch->GetAttackType(NULL), NULL, 0); if (ret == -1) return ; } }
void do_GMSummon(CPC *a1, char *a2) { int v3; // [sp+28h] [bp-20h]@21 int v4; // [sp+2Ch] [bp-1Ch]@21 CNPC *v6; // [sp+34h] [bp-14h]@12 int v8; // [sp+3Ch] [bp-Ch]@10 char v9; // [sp+43h] [bp-5h]@5 char *s; // [sp+44h] [bp-4h]@4 if(a2) { if(*a2) { TrimString(a2); s = a2; if(strlen(a2)) { v9 = 0; while(*s) { if(!(*(short *)(_ctype_b + 2 * *s) & 0x800)) { v9 = 1; break; } ++s; } v8 = -1; if(!v9) v8 = atoi(a2); v6 = 0; if(v9) { for(int i = 0; i < gserver.Unk452200.Unk4; ++i) { if(!strcmp(gserver.Unk452200.Unk0[i].Unk4, a2)) { v6 = gserver.Unk452200.Create(gserver.Unk452200.Unk0[i].Unk0); break; } } } else { v6 = gserver.Unk452200.Create(v8); } if(v6) { v6->Unk120.Unk0 = a1->Unk120.Unk0 + 2.0; v6->Unk120.Unk16 = a1->Unk120.Unk16; v6->Unk120.Unk4 = a1->Unk120.Unk4 + 2.0; v6->Unk120.Unk12 = GetRandom(0, 62831) / 10000; v6->Unk476 = v6->Unk120.Unk0; v6->Unk480 = v6->Unk120.Unk16; v6->Unk484 = v6->Unk120.Unk4; v6->Unk752 = 0; a1->Unk412->AddNPC(v6); a1->Unk412->PointToCellNum(v6->Unk120.Unk0, v6->Unk120.Unk4, &v4, &v3); a1->Unk412->CharToCell(v6, v6->Unk120.Unk16, v4, v3); CNetMsg v2; AppearMsg(v2, v6, 1); a1->Unk412->SendToCell(v2, v6->Unk120.Unk16, v4, v3, 4); } } } } }
void M_Reanimate (edict_t *ent, edict_t *target, int r_level, float r_modifier, qboolean printMsg) { vec3_t bmin, bmax; edict_t *e; if (!strcmp(target->classname, "drone")) { // if the summoner is a player, check for sufficient monster slots if (ent->client && (ent->num_monsters + target->monsterinfo.control_cost > MAX_MONSTERS)) return; target->monsterinfo.level = r_level; M_SetBoundingBox(target->mtype, bmin, bmax); if (G_IsValidLocation(target, target->s.origin, bmin, bmax) && M_Initialize(ent, target)) { // restore this drone target->monsterinfo.slots_freed = false; // reset freed flag target->health = r_modifier*target->max_health; target->monsterinfo.power_armor_power = r_modifier*target->monsterinfo.max_armor; target->monsterinfo.resurrected_time = level.time + 10.0; target->activator = ent; // transfer ownership! target->nextthink = level.time + 1.0; gi.linkentity(target); target->monsterinfo.stand(target); ent->num_monsters += target->monsterinfo.control_cost; // make sure invasion monsters hunt for navi if (invasion->value && !ent->client && ent->activator && !ent->activator->client) { target->monsterinfo.aiflags &= ~AI_STAND_GROUND; target->monsterinfo.aiflags |= AI_FIND_NAVI; } if (ent->client && printMsg) gi.cprintf(ent, PRINT_HIGH, "Resurrected a %s. (%d/%d)\n", target->classname, ent->num_monsters, MAX_MONSTERS); } } else if ((!strcmp(target->classname, "bodyque") || !strcmp(target->classname, "player"))) { int random=GetRandom(1, 3); vec3_t start; // if the summoner is a player, check for sufficient monster slots if (ent->client && (ent->num_monsters + 1 > MAX_MONSTERS)) return; e = G_Spawn(); VectorCopy(target->s.origin, start); // kill the corpse T_Damage(target, target, target, vec3_origin, target->s.origin, vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, 0); //4.2 random soldier type with different weapons if (random == 1) { // blaster e->mtype = M_SOLDIER; e->s.skinnum = 0; } else if (random == 2) { // rocket e->mtype = M_SOLDIERLT; e->s.skinnum = 4; } else { // shotgun e->mtype = M_SOLDIERSS; e->s.skinnum = 2; } e->activator = ent; e->monsterinfo.level = r_level; M_Initialize(ent, e); e->health = r_modifier*e->max_health; e->monsterinfo.power_armor_power = r_modifier*e->monsterinfo.max_armor; e->monsterinfo.resurrected_time = level.time + 10.0; e->s.skinnum |= 1; // injured skin e->monsterinfo.stand(e); if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { start[2] += 24; if (!G_IsValidLocation(target, start, e->mins, e->maxs)) { G_FreeEdict(e); return; } } VectorCopy(start, e->s.origin); gi.linkentity(e); e->nextthink = level.time + 1.0; ent->num_monsters += e->monsterinfo.control_cost; // make sure invasion monsters hunt for navi if (invasion->value && !ent->client && ent->activator && !ent->activator->client) { target->monsterinfo.aiflags &= ~AI_STAND_GROUND; target->monsterinfo.aiflags |= AI_FIND_NAVI; } if (ent->client && printMsg) gi.cprintf(ent, PRINT_HIGH, "Resurrected a soldier. (%d/%d)\n", ent->num_monsters, MAX_MONSTERS); } else if (!strcmp(target->classname, "spiker")) { // if the summoner is a player, check for sufficient spiker slots if (ent->client && (ent->num_spikers + 1 > SPIKER_MAX_COUNT)) return; e = CreateSpiker(ent, r_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_spikers--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->health = r_modifier * e->max_health; e->monsterinfo.resurrected_time = level.time + 10.0; e->s.frame = 4; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); if (ent->client && printMsg) gi.cprintf(ent, PRINT_HIGH, "Resurrected a spiker. (%d/%d)\n", ent->num_spikers, SPIKER_MAX_COUNT); } else if (!strcmp(target->classname, "obstacle")) { // if the summoner is a player, check for sufficient obstacle slots if (ent->client && (ent->num_obstacle + 1 > OBSTACLE_MAX_COUNT)) return; e = CreateObstacle(ent, r_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_obstacle--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->monsterinfo.resurrected_time = level.time + 10.0; e->health = r_modifier * e->max_health; e->s.frame = 6; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); if (ent->client && printMsg) gi.cprintf(ent, PRINT_HIGH, "Resurrected an obstacle. (%d/%d)\n", ent->num_obstacle, OBSTACLE_MAX_COUNT); } else if (!strcmp(target->classname, "gasser")) { // if the summoner is a player, check for sufficient gasser slots if (ent->client && (ent->num_gasser + 1 > GASSER_MAX_COUNT)) return; e = CreateGasser(ent, r_level); // make sure the new entity fits if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs)) { ent->num_gasser--; G_FreeEdict(e); return; } VectorCopy(target->s.angles, e->s.angles); e->s.angles[PITCH] = 0; e->monsterinfo.cost = target->monsterinfo.cost; e->monsterinfo.resurrected_time = level.time + 10.0; e->health = r_modifier * e->max_health; e->s.frame = 0; VectorCopy(target->s.origin, e->s.origin); gi.linkentity(e); organ_remove(target, false); if (ent->client && printMsg) gi.cprintf(ent, PRINT_HIGH, "Resurrected a gasser. (%d/%d)\n", ent->num_gasser, GASSER_MAX_COUNT); } }
void do_Attack(CPC* pc, CNetMsg::SP& msg) { CDratanCastle * pCastle = CDratanCastle::CreateInstance(); pCastle->CheckRespond(pc); RequestClient::doAttack* packet = reinterpret_cast<RequestClient::doAttack*>(msg->m_buf); // 동시 공격은 최대 5 if (packet->multicount > 5) { LOG_ERROR("HACKING : invalid multi count[%d]. charIndex[%d]", packet->multicount, pc->m_index); pc->m_desc->Close("invalid multi count"); return; } // multi target의 중복 검사 if (packet->multicount > 1) { std::set<int> tset; for (int i = 0; i < packet->multicount; ++i) { if (tset.insert(packet->list[i].index).second == false) { LOG_ERROR("HACKING : duplicate multi target[%d]. charIndex[%d]", packet->list[i].index, pc->m_index); pc->m_desc->Close("duplicate multi target"); return; } } } // 대상 검색 : 인접 셀에서만 CArea* area = pc->m_pArea; if (area == NULL) return; CCharacter* ch = area->FindCharInCell(pc, packet->aIndex, (MSG_CHAR_TYPE)packet->aCharType); if (ch == NULL) return; CCharacter* tch = area->FindCharInCell(ch, packet->tIndex, (MSG_CHAR_TYPE)packet->tCharType); if (tch == NULL) return; // 공격자가 PC이면 자신의 캐릭만 조정 if (IS_PC(ch) && ch != pc) return ; switch (ch->m_type) { case MSG_CHAR_PC: { if( IS_NPC(tch)) { CPC * pPC = TO_PC(ch); CNPC * pNPC = TO_NPC(tch); if( pPC->GetSummonNpc(SUMMON_NPC_TYPE_MERCENARY) == pNPC ) return; } //pvp보호 아이템 체크 if (checkPvPProtect(pc, tch) == false) return; // 공격 거리 검사 if (GetDistance(ch, tch) > ch->m_attackRange * 2) return ; // 공속 검사 if ( ch->ChekAttackType() && ch->CheckHackAttack(pc)) return ; // 펫 타고 있으면 불가능 if (pc->GetPet() && pc->GetPet()->IsMount()) return ; // 공성 아이템 착용시 해당 스킬 발동 int mixSkillIndex[] = { pc->m_opSturnIndex, pc->m_opBloodIndex, pc->m_opPoisonIndex, pc->m_opSlowIndex, pc->m_opMoveIndex }; int mixSkillLevel[] = { pc->m_opSturnLevel, pc->m_opBloodLevel, pc->m_opPoisonLevel, pc->m_opSlowLevel, pc->m_opMoveLevel }; CSkill* skillMixItem = NULL; int i; int bStop = 0; for (i = 0; i < 5; i++) { if (mixSkillIndex[i] > 0 && mixSkillLevel[i] > 0) { skillMixItem = gserver->m_skillProtoList.Create(mixSkillIndex[i], mixSkillLevel[i]); if (skillMixItem) { bool bApply; bStop = ApplySkill(ch, tch, skillMixItem, -1, bApply); } delete skillMixItem; skillMixItem = NULL; if (bStop != 0) return ; } } if (IS_PC(ch)) { CPC* pPCAttacker = TO_PC(ch); CItem* weaponItem = pPCAttacker->m_wearInventory.wearItemInfo[WEARING_WEAPON]; // 암흑 공격 if (pPCAttacker->m_opAttackBlind > 0) { CSkill* pSkillBlind = gserver->m_skillProtoList.Create(415, pPCAttacker->m_opAttackBlind); int nRetApplySkill = 0; if (pSkillBlind) { bool bApply; nRetApplySkill = ApplySkill(ch, tch, pSkillBlind, -1, bApply); } delete pSkillBlind; pSkillBlind = NULL; if (nRetApplySkill != 0) return ; } // 독 공격 if (pPCAttacker->m_opAttackPoison > 0) { CSkill* pSkillPoison = gserver->m_skillProtoList.Create(414, pPCAttacker->m_opAttackPoison); int nRetApplySkill = 0; if (pSkillPoison) { bool bApply; nRetApplySkill = ApplySkill(ch, tch, pSkillPoison, -1, bApply); } delete pSkillPoison; pSkillPoison = NULL; if (nRetApplySkill != 0) return ; } } } // PC 검사 break; case MSG_CHAR_PET: case MSG_CHAR_ELEMENTAL: // TODO : 소환수 공속 검사 // 공격 거리 검사 if (GetDistance(ch, tch) > ch->m_attackRange * 2) return ; // 공속 검사 if (ch->CheckHackAttack(pc)) return ; break; default: break; } if(IS_PC(tch)) { if( TO_PC(tch)->m_bImmortal == true ) return; } if (DEAD(ch) || !ch->CanAttack() || pc->IsDisable()) return ; // 결계걸린 대상은 공격 못한다. if ( tch->m_assist.m_state & AST_FREEZE ) return; //무적 버프 대상은 공격할 수 없다. if ( tch->m_assist.m_state & AST_SAFEGUARD ) { CNetMsg::SP rmsg(new CNetMsg); SysMsg(rmsg, MSG_SYS_DO_NOT_ATTACK_IMMOTAL); SEND_Q(rmsg, pc->m_desc); return; } // 대상이 NPC일때만 멀티 공격 if (!IS_NPC(tch)) packet->multicount = 0; // 최소한 공격 1회 이상 bool bAttacked = false; bool bAttackedPet = false; // 애완동물은 NPC상대시 레벨 검사 // 멀티 공격 검사용 std::set<int> listMultiTarget; while (tch) { bool bBlocked = false; // NPC를 공격할 때에만 속성맵 검사 (프리PK 지역이 아닐때만) if ( IS_NPC(tch) && !(tch->GetMapAttr() & MATT_FREEPKZONE) ) { char tempy = GET_YLAYER(ch); bBlocked = (!area->IsNotBlocked(ch, tch, true, tempy)); } int ret = 0; if (!bBlocked) { if (IS_PC(ch) && ch->IsEnemy(tch)) { bAttacked = true; #ifdef MONSTER_AI if (tch != NULL && IS_NPC(tch)) { CNPC * pTemp = TO_NPC(tch); if (pTemp != NULL) { if (ch->m_level - tch->m_level <= 5 && pTemp->m_proto->m_index != 303 /*악마의 묘지*/) { bAttackedPet = true; } if (pTemp->m_bMoveLock || pTemp->m_bMoveToRegen) { pTemp->m_bMoveToRegen = false; pTemp->m_bMoveLock = false; pTemp->m_pulseMoveLock = 0; pTemp->m_postregendelay = 0; } } } #else if (tch != NULL && IS_NPC(tch) && ch->m_level - tch->m_level <= 5) { CNPC * pTemp = TO_NPC(tch); if (pTemp != NULL && pTemp->m_proto->m_index != 303 /*악마의 묘지*/) { bAttackedPet = true; } } #endif } listMultiTarget.insert(tch->m_index); ret = ProcAttack(ch, tch, ch->GetAttackType(NULL), NULL, 0); } if (ret == -1 || tch->m_index == -1) // ProcAttack()안에서 Character 객체가 소멸된 경우도 포함 { tch = NULL; continue ; } //공격 발동형 스킬 추가 if( pc->m_optionAttSkillList.count() > 0 ) { //공격 할 시에 적에게 스킬 적용 void* pos = pc->m_optionAttSkillList.GetHeadPosition(); bool bApply = false; while (pos) { CSkill* skill = pc->m_passiveSkillList.GetNext(pos); if (skill && skill->m_proto) { int rand = GetRandom(1, 10000); if( rand < skill->m_optionSkillProb ) { ApplySkill(ch, tch, skill, -1, bApply); if(bApply == false) { GAMELOG << init("EVENT_PCBANG_2NDS SKILL FAILED (LOGIN) ", pc ) << end;// 스킬 적용 실패 } } } } } if (area->m_zone->IsPersonalDungeon() == false) { tch = NULL; continue; } if (packet->multicount && !DEAD(ch)) { int multitarget = packet->list[packet->multicount].index; --packet->multicount; tch = area->FindCharInCell(ch, multitarget, (MSG_CHAR_TYPE)packet->tCharType); if (tch == NULL) { continue; } if (GetDistance(ch, tch) > ch->m_attackRange * 2) { tch = NULL; continue; } std::set<int>::iterator it = listMultiTarget.find(tch->m_index); if (it != listMultiTarget.end()) { GAMELOG << init("HACK ATTACK MULTI TARGET", pc) << "ZONE" << delim << pc->m_pZone->m_index << delim << "TARGET" << delim << packet->tCharType << delim << multitarget << end; if (pc->m_desc->IncreaseHackCount(1)) return ; tch = NULL; } } else { tch = NULL; continue; } if (packet->multicount <= 0) { tch = NULL; continue; } } // end while if (bAttackedPet && !ch->IsInPeaceZone(true)) pc->m_pulseLastAttackSkill = gserver->m_pulse; #ifdef EVENT_SEARCHFRIEND_TIME // 공격시 이벤트 시간 갱신 검사 if (gserver->m_bSearchFriendEvent && (pc->m_nEventSearchFriendListCount >= 1) && (pc->m_bEventSearchFriendSelect == true) && (pc->m_nTimeEventSearchFriend <= 216000) && bAttacked && !ch->IsInPeaceZone(true)) pc->m_pulseEventSearchFriend = gserver->m_pulse; #endif // #ifdef EVENT_SEARCHFRIEND_TIME }
void Body::HandleModelString(ArgList* pArgList) { if (!g_pLTServer || !pArgList || !pArgList->argv || pArgList->argc == 0) return; char* pKey = pArgList->argv[0]; if (!pKey) return; LTBOOL bSlump = !_stricmp(pKey, s_szKeyNoise); LTBOOL bLand = !_stricmp(pKey, s_szKeyLand); if ( bSlump || bLand ) { // Hitting the ground noise /* SurfaceType eSurface = ST_UNKNOWN; CollisionInfo Info; g_pLTServer->GetStandingOn(m_hObject, &Info); if (Info.m_hPoly && Info.m_hPoly != INVALID_HPOLY) { eSurface = (SurfaceType)GetSurfaceType(Info.m_hPoly); } else if (Info.m_hObject) // Get the texture flags from the object... { eSurface = (SurfaceType)GetSurfaceType(Info.m_hObject); } else { return; } */ LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_From = vPos; IQuery.m_To = vPos - LTVector(0,96,0); IQuery.m_Flags = INTERSECT_OBJECTS | INTERSECT_HPOLY | IGNORE_NONSOLID; IQuery.m_FilterFn = GroundFilterFn; SurfaceType eSurface; g_cIntersectSegmentCalls++; if (g_pLTServer->IntersectSegment(&IQuery, &IInfo)) { if (IInfo.m_hPoly && IInfo.m_hPoly != INVALID_HPOLY) { eSurface = (SurfaceType)GetSurfaceType(IInfo.m_hPoly); } else if (IInfo.m_hObject) // Get the texture flags from the object... { eSurface = (SurfaceType)GetSurfaceType(IInfo.m_hObject); } else { return; } } else { return; } SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurface); _ASSERT(pSurf); if (!pSurf) return; // Update the noise info. We use a time in the future so AI's don't *instantly* react to the sound // AI's twice as sensitive to landing sound (because it's louder) m_DeathScene.SetNoise(pSurf->fDeathNoiseModifier * (bLand ? 2.0f : 1.0f), g_pLTServer->GetTime() + GetRandom(0.5f, 1.0f)); } }
void CLineSystemFX::AddLine(int nIndex, LTBOOL bSetInitialPos) { if (!m_hServerObject || !m_pLines || nIndex < 0 || nIndex >= m_nTotalNumLines) return; LTVector vPos, vCamPos, vObjPos, vDist, vVel; LTLine line; g_pLTClient->GetObjectPos(m_hServerObject, &vObjPos); // Get the camera's position...If the camera is too far away from // the line being added, don't add it :) HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; g_pLTClient->GetObjectPos(hCamera, &vCamPos); vCamPos.y = 0.0f; // Only take x/z into account... vPos.x = GetRandom(-m_cs.vDims.x, m_cs.vDims.x); vPos.y = GetRandom(-m_cs.vDims.y, m_cs.vDims.y); vPos.z = GetRandom(-m_cs.vDims.z, m_cs.vDims.z); LTFLOAT fLifetime = m_cs.fLineLifetime; vVel.x = GetRandom(m_cs.vMinVel.x, m_cs.vMaxVel.x); vVel.y = GetRandom(m_cs.vMinVel.y, m_cs.vMaxVel.y); vVel.z = GetRandom(m_cs.vMinVel.z, m_cs.vMaxVel.z); // If we need to set the initial line pos... if (bSetInitialPos) { fLifetime = GetRandom(0.0f, m_cs.fLineLifetime); if (fLifetime >= 0.0f) { vPos += (vVel * (m_cs.fLineLifetime - fLifetime)); } else { fLifetime = m_cs.fLineLifetime; } } vObjPos += vPos; vObjPos.y = 0.0f; // Only take x/z into account vDist = vCamPos - vObjPos; if (vDist.MagSqr() < m_fMaxViewDistSqr || bSetInitialPos) { line.m_Points[0].m_Pos = vPos + m_vStartOffset; line.m_Points[0].r = m_cs.vStartColor.x; line.m_Points[0].g = m_cs.vStartColor.y; line.m_Points[0].b = m_cs.vStartColor.z; line.m_Points[0].a = m_cs.fStartAlpha; line.m_Points[1].m_Pos = vPos + m_vEndOffset; line.m_Points[1].r = m_cs.vEndColor.x; line.m_Points[1].g = m_cs.vEndColor.y; line.m_Points[1].b = m_cs.vEndColor.z; line.m_Points[1].a = m_cs.fEndAlpha; if (m_pLines[nIndex].hLTLine) { m_pClientDE->SetLineInfo(m_pLines[nIndex].hLTLine, &line); } else { m_pLines[nIndex].hLTLine = m_pClientDE->AddLine(m_hObject, &line); m_snTotalLines++; } m_pLines[nIndex].fLifetime = fLifetime; m_pLines[nIndex].vVel = vVel; } else { RemoveLine(nIndex); } }
int main(int argc, char *argv[]) { #include "setRootCase.H" #include "createTime.H" #include "createMesh.H" #include "createFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Info << "\n setting particle positions \n" << endl; word positioningType ( setParticlePositionsPelletDict.lookup("positioningType") ); if(positioningType == "pellet") { dictionary autoPelletPositionSubDict ( setParticlePositionsPelletDict.subDict("autoPelletPositionSubDict") ); scalar particleDiameter ( readScalar(autoPelletPositionSubDict.lookup("particleDiameter")) ); label particleNumber ( readLabel(autoPelletPositionSubDict.lookup("particleNumber")) ); scalar radius ( readScalar(autoPelletPositionSubDict.lookup("radius")) ); scalar length ( readScalar(autoPelletPositionSubDict.lookup("length")) ); vector origin ( autoPelletPositionSubDict.lookup("origin") ); label trialNum ( readLabel(autoPelletPositionSubDict.lookup("trialNumber")) ); label densityR ( readLabel(autoPelletPositionSubDict.lookup("densityRadius")) ); label densityT ( readLabel(autoPelletPositionSubDict.lookup("densityTheta")) ); label densityL ( readLabel(autoPelletPositionSubDict.lookup("densityLength")) ); // Min and Max of each variable were multiplied by densityR,T,L respectively to increase the resolution, since random function I made can only output integer. // by doing so, it can output decimal value. scalar thetaMin = 0*densityT; scalar thetaMax = 360 * densityT; scalar rMin = 0*densityR; scalar rMax = radius * densityR; scalar lMin = -(length-particleDiameter)*densityL/2; scalar lMax = (length-particleDiameter)*densityL/2; //dummy list to store particles in cylindrical coordinates x is r, y is theta, z is length List<vector> dummyCylindic(trialNum); //dummy list to store particles in rectangula coordinates List<vector> dummyRectangula(trialNum); //List for particles settled in cylindrical coordinates List<vector> cylindic(particleNumber); //List for particles transformed into rectangular coordinates List<vector> rectangula(particleNumber); // the first particle is stored in cylindic and rectangula list cylindic[0].x() = GetRandom(rMin,rMax)/densityR; cylindic[0].y() = GetRandom(thetaMin,thetaMax)/densityT; cylindic[0].z() = GetRandom(lMin,lMax)/densityL; Info << "r is" << cylindic[0].x() << endl; Info << "theta is" << cylindic[0].y() << endl; Info << "length is " << cylindic[0].z() << endl; // cylindic[0] is transormed into rectangular coordinates //inside sin is written in radian rectangula[0].x() = cylindic[0].x()*Foam::sin(constant::mathematical::pi*cylindic[0].y()/180); rectangula[0].y() = cylindic[0].z(); rectangula[0].z() = cylindic[0].x()*Foam::cos(constant::mathematical::pi*cylindic[0].y()/180); Info << "x is" << rectangula[0].x() << endl; Info << "y is" << rectangula[0].y() << endl; Info << "z is " << rectangula[0].z() << endl; label l = 0; forAll(dummyCylindic,i) { if( l< particleNumber-1 ) { dummyCylindic[i].x() = GetRandom(rMin,rMax)/densityR; dummyCylindic[i].y() = GetRandom(thetaMin,thetaMax)/densityT; dummyCylindic[i].z() = GetRandom(lMin,lMax)/densityL; Info << " dummyCylindic[ "<<i<<"].x()" << dummyCylindic[i].x() << endl; Info << " dummyCylindic[ "<<i<<"].y()" << dummyCylindic[i].y() << endl; Info << " dummyCylindic[ "<<i<<"].z()" << dummyCylindic[i].z() << endl; dummyRectangula[i].x() = dummyCylindic[i].x()*Foam::sin(constant::mathematical::pi*dummyCylindic[i].y()/180); dummyRectangula[i].y() = dummyCylindic[i].z(); dummyRectangula[i].z() = dummyCylindic[i].x()*Foam::cos(constant::mathematical::pi*dummyCylindic[i].y()/180); label counter = 0; label t; for(t=0; t<=l; t++) { scalar S; S = mag(dummyRectangula[i]-rectangula[t]); if(S>particleDiameter) { counter += 1; }else{ counter += 0; } } if(counter == l+1) { l = l+1; rectangula[l] = dummyRectangula[i]; } } } fileName rootName(runTime.path()); fileName fName("particlePositionsPellet"); OFstream os(rootName/fName); Info<< "Writing to the output file"<<endl; label k; for(k=0; k<=l; k++) { rectangula[k] += origin ; } for(k=0; k<=l; k++) { os <<"("<<rectangula[k].x()<<" "<<rectangula[k].y()<<" "<<rectangula[k].z()<<")"<<endl; } Info<< "End\n" << endl; }
void CLaserBeam::Update(LTVector &vBeamStartPos, const LTRotation* pRDirRot, LTBOOL b3rdPerson, LTBOOL bDetect) { if (!m_bOn) return; // Calculate beam position... HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (!hPlayerObj) return; HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL}; IntersectQuery qInfo; IntersectInfo iInfo; LTVector vPos(0, 0, 0); LTRotation rRot; LTVector vU, vR, vF; if (pRDirRot && b3rdPerson) { vPos = vBeamStartPos; vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); } else { g_pLTClient->GetObjectRotation(hCamera, &rRot); g_pLTClient->GetObjectPos(hCamera, &vPos); vU = rRot.Up(); vR = rRot.Right(); vF = rRot.Forward(); if (g_cvarLaserBeamDebug.GetFloat() == 0.0f) { vBeamStartPos += vPos; } else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f) { vBeamStartPos = vPos; } else if (pRDirRot) { vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); vBeamStartPos = vBeamStartPos; } } LTVector vEndPos = vPos + (vF * 10000.0f); qInfo.m_From = vPos; qInfo.m_To = vEndPos; qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; qInfo.m_FilterFn = ObjListFilterFn; qInfo.m_pUserData = hFilterList; if (g_pLTClient->IntersectSegment(&qInfo, &iInfo)) { vEndPos = iInfo.m_Point; } // Show the light beam... LTVector vColor = LTVector(GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f), GetRandom(35.0f, 55.0f));; LTFLOAT fAlpha = g_cvarLaserBeamAlpha.GetFloat(); if (iInfo.m_hObject && bDetect) { uint32 dwUsrFlgs = 0; g_pCommonLT->GetObjectFlags(iInfo.m_hObject, OFT_User, dwUsrFlgs); if (dwUsrFlgs & USRFLG_CHARACTER) { fAlpha = 0.95f; vColor.Init(GetRandom(35.0f, 55.0f), GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f));; } } LTFLOAT fWidth = g_cvarLaserBeamThickness.GetFloat(); fWidth = b3rdPerson ? fWidth*2.0f : fWidth; vBeamStartPos += (vF * g_cvarLaserBeamFOffset.GetFloat()); vBeamStartPos += (vR * g_cvarLaserBeamROffset.GetFloat()); vBeamStartPos += (vU * g_cvarLaserBeamUOffset.GetFloat()); PLFXCREATESTRUCT pls; if (g_cvarLaserBeamDebug.GetFloat() >= 0.0f) { // g_pLTClient->CPrint("StartPos = %.2f, %.2f, %.2f", VEC_EXPAND(vBeamStartPos)); // g_pLTClient->CPrint("EndPos = %.2f, %.2f, %.2f", VEC_EXPAND(vEndPos)); } pls.vStartPos = vBeamStartPos; pls.vEndPos = vEndPos; pls.vInnerColorStart = vColor; pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = fAlpha; pls.fAlphaEnd = fAlpha; pls.fMinWidth = 0; pls.fMaxWidth = fWidth; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 1.0f; pls.fAlphaLifeTime = 1.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTTRUE; pls.bAlignFlat = b3rdPerson ? LTFALSE : LTTRUE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = (int)g_cvarLaserBeamNumSegments.GetFloat(); if (m_LightBeam.HasBeenDrawn()) { // Keep the light beam in the vis list... m_LightBeam.SetPos(vBeamStartPos); // Hide the beam in portals if 1st person...Also set flag really // close to true... uint32 dwFlags2, dwFlags; dwFlags = m_LightBeam.GetFlags(); dwFlags2 = m_LightBeam.GetFlags2(); if (b3rdPerson) { dwFlags &= ~FLAG_REALLYCLOSE; } else { if (g_cvarLaserBeamDebug.GetFloat() > 1.0f) { dwFlags |= FLAG_REALLYCLOSE; pls.bUseObjectRotation = LTTRUE; } } m_LightBeam.SetFlags(dwFlags); m_LightBeam.SetFlags2(dwFlags2); m_LightBeam.ReInit(&pls); } else { m_LightBeam.Init(&pls); m_LightBeam.CreateObject(g_pLTClient); } m_LightBeam.Update(); }
/** Handles movement of joined local player. */ void Client::UpdateLocalPlayer(float dt) { SPADES_MARK_FUNCTION(); auto *player = world->GetLocalPlayer(); PlayerInput inp = playerInput; WeaponInput winp = weapInput; // weapon/tools are disabled while/soon after sprinting if(GetSprintState() > 0.001f) { winp.primary = false; winp.secondary = false; } // don't allow to stand up when ceilings are too low if(inp.crouch == false){ if(player->GetInput().crouch){ if(!player->TryUncrouch(false)){ inp.crouch = true; } } } // don't allow jumping in the air if(inp.jump){ if(!player->IsOnGroundOrWade()) inp.jump = false; } // weapon/tools are disabled while changing tools if(clientPlayers[world->GetLocalPlayerIndex()]->IsChangingTool()) { winp.primary = false; winp.secondary = false; } // disable weapon while reloading (except shotgun) if(player->GetTool() == Player::ToolWeapon && player->IsAwaitingReloadCompletion() && !player->GetWeapon()->IsReloadSlow()) { winp.primary = false; } player->SetInput(inp); player->SetWeaponInput(winp); //send player input // FIXME: send only there are any changed? net->SendPlayerInput(inp); net->SendWeaponInput(winp); if(hasDelayedReload) { world->GetLocalPlayer()->Reload(); net->SendReload(); hasDelayedReload = false; } //PlayerInput actualInput = player->GetInput(); WeaponInput actualWeapInput = player->GetWeaponInput(); if(actualWeapInput.secondary && player->IsToolWeapon() && player->IsAlive()){ }else{ if(player->IsToolWeapon()){ // there is a possibility that player has respawned or something. // stop aiming down weapInput.secondary = false; } } // is the selected tool no longer usable (ex. out of ammo)? if(!player->IsToolSelectable(player->GetTool())) { // release mouse button before auto-switching tools winp.primary = false; winp.secondary = false; weapInput = winp; net->SendWeaponInput(weapInput); actualWeapInput = winp = player->GetWeaponInput(); // select another tool Player::ToolType t = player->GetTool(); do{ switch(t){ case Player::ToolSpade: t = Player::ToolGrenade; break; case Player::ToolBlock: t = Player::ToolSpade; break; case Player::ToolWeapon: t = Player::ToolBlock; break; case Player::ToolGrenade: t = Player::ToolWeapon; break; } }while(!world->GetLocalPlayer()->IsToolSelectable(t)); SetSelectedTool(t); } // send orientation Vector3 curFront = player->GetFront(); if(curFront.x != lastFront.x || curFront.y != lastFront.y || curFront.z != lastFront.z) { lastFront = curFront; net->SendOrientation(curFront); } lastKills = world->GetPlayerPersistent(player->GetId()).kills; // show block count when building block lines. if(player->IsAlive() && player->GetTool() == Player::ToolBlock && player->GetWeaponInput().secondary && player->IsBlockCursorDragging()) { if(player->IsBlockCursorActive()) { auto blocks = std::move (world->CubeLine(player->GetBlockCursorDragPos(), player->GetBlockCursorPos(), 256)); auto msg = _TrN("Client", "{0} block", "{0} blocks", blocks.size()); AlertType type = static_cast<int>(blocks.size()) > player->GetNumBlocks() ? AlertType::Warning : AlertType::Notice; ShowAlert(msg, type, 0.f, true); }else{ // invalid auto msg = _Tr("Client", "-- blocks"); AlertType type = AlertType::Warning; ShowAlert(msg, type, 0.f, true); } } if(player->IsAlive()) lastAliveTime = time; if(player->GetHealth() < lastHealth){ // ouch! lastHealth = player->GetHealth(); lastHurtTime = world->GetTime(); Handle<IAudioChunk> c; switch((rand() >> 3) & 3){ case 0: c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal1.wav"); break; case 1: c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal2.wav"); break; case 2: c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal3.wav"); break; case 3: c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal4.wav"); break; } audioDevice->PlayLocal(c, AudioParam()); float hpper = player->GetHealth() / 100.f; int cnt = 18 - (int)(player->GetHealth() / 100.f * 8.f); hurtSprites.resize(std::max(cnt, 6)); for(size_t i = 0; i < hurtSprites.size(); i++) { HurtSprite& spr = hurtSprites[i]; spr.angle = GetRandom() * (2.f * static_cast<float>(M_PI)); spr.scale = .2f + GetRandom() * GetRandom() * .7f; spr.horzShift = GetRandom(); spr.strength = .3f + GetRandom() * .7f; if(hpper > .5f) { spr.strength *= 1.5f - hpper; } } }else{