bool csConsoleOutput::Initialize (iObjectRegistry *object_reg) { csConsoleOutput::object_reg = object_reg; G3D = csQueryRegistry<iGraphics3D> (object_reg); if (!G3D) return false; G2D = G3D->GetDriver2D (); csConfigAccess Config (object_reg, "/config/standardcon.cfg"); const char* fontname = Config->GetStr ("StandardConsole.ConFont", "auto"); int fontsize = Config->GetInt ("StandardConsole.ConFontSize", 10); transparent = Config->GetBool ("StandardConsole.TranspBG", false); // Initialize the display rectangle to the entire display size.Set (0, 0, G2D->GetWidth () - 1, G2D->GetHeight () - 1); invalid.Set (size); // Invalidate the entire console int fw, fh; csRef<iFontServer> fserv = G2D->GetFontServer(); if (fserv) { if (!strcasecmp (fontname, "auto")) { // choose a font that allows at least 80 columns of text if (G2D->GetWidth () <= 560) fontname = CSFONT_SMALL; else if (G2D->GetWidth () <= 640) fontname = CSFONT_COURIER; else fontname = CSFONT_LARGE; fontsize = 10; } font = fserv->LoadFont (fontname, fontsize); font->GetMaxSize (fw, fh); } else { fw = fh = 20; csReport (object_reg, CS_REPORTER_SEVERITY_WARNING, "crystalspace.console.output.standard", "csConsoleOutput: Unable to locate iFontServer"); } // Create the backbuffer (4096 lines max) buffer = new csConsoleBuffer (4096, (size.Height() / (fh + 2))); // Initialize flash_time for flashing cursors flash_time = csGetTicks (); // We want to see broadcast events CS_INITIALIZE_SYSTEM_EVENT_SHORTCUTS (object_reg); if (!eventHandler) eventHandler.AttachNew (new EventHandler (this)); csRef<iEventQueue> q (csQueryRegistry<iEventQueue> (object_reg)); if (q.IsValid()) { csEventID events[3] = { SystemOpen, SystemClose, CS_EVENTLIST_END }; q->RegisterListener (eventHandler, events); } return true; }
PendingInvite::PendingInvite( Client *inviter, Client *invitee, bool penalize, const char *question_str, const char *accept_button, const char *reject_button, const char *inviter_explanation, const char *invitee_explanation, const char *inviter_acceptance, const char *invitee_acceptance, const char *inviter_rejection, const char *invitee_rejection, psQuestionMessage::questionType_t invType) : PendingQuestion(invitee->GetClientNum(), question_str, invType) { // Disable incoming invitations while dueling (invites could be used to distract and cheat) if (invitee->GetDuelClientCount() && invType != psQuestionMessage::duelConfirm) { psserver->SendSystemError(inviter->GetClientNum(), "%s is distracted with a duel", invitee->GetName() ); ok = false; return; } /* Invite spam is checked for when the penalize flag is on. * The penalty level increases with each consecutive decline. (set in invitemanager.h) * It can expire with time, or be lowered on acceptace by a "reputable player". * Penalties: * 1st) 1 min lockout * 2nd) 5 min lockout + warning * 3rd) 10 min lockout + 10 point fine(s) (advisor) + death * 4th) 30 point fine(s) + death + kick from server (level reset to 3rd after this) */ if (penalize && CheckForSpam(inviter, invType)) { ok = false; return; } inviterClientNum = inviter->GetClientNum(); question = question_str; accept = accept_button; reject = reject_button; inviterAcceptance = inviter_acceptance; inviteeAcceptance = invitee_acceptance; inviterRejection = inviter_rejection; inviteeRejection = invitee_rejection; inviterName = inviter->GetName(); inviteeName = invitee->GetName(); cannotAccept = false; psserver->SendSystemInfo(invitee->GetClientNum(), invitee_explanation, inviter->GetName() ); psserver->SendSystemInfo(inviter->GetClientNum(), inviter_explanation, invitee->GetName() ); inviter->SetLastInviteTime(csGetTicks()); }
void pawsGroupWindow::Draw() { GEMClientActor* player = psengine->GetCelClient()->GetMainPlayer(); player->GetVitalMgr()->Predict( csGetTicks(),"Self" ); if (memberList->GetRowCount()>0) SetStats( player ); pawsWidget::Draw(); }
void OSXAssistant::advance_state() { csRef<iVirtualClock> c = get_virtual_clock(); if (c.IsValid()) c->Advance(); csRef <iEventQueue> q = get_event_queue(); if (q.IsValid()) { csTicks previous = csGetTicks (); q->Process(); // Limit fps. csTicks elapsed = csGetTicks () - previous; if (elapsed < min_elapsed) csSleep (min_elapsed - elapsed); } if (!continue_running()) OSXDelegate_stop_event_loop(controller); }
void psLinearMovement::UpdateDR () { csTicks time = csGetTicks(); if (lastDRUpdate) { float delta = time - lastDRUpdate; delta /= 1000; ExtrapolatePosition (delta); } lastDRUpdate = time; }
void SoundSystemManager::Update () { SndTime = csGetTicks(); // call it all 100 Ticks if (Initialised && LastUpdateTime + 100 <= SndTime) { UpdateSound(); // make a update on sounddata to check if there are sounds to unload soundData->Update(); } }
Tribe::Tribe(EventManager* eventmngr, RecipeManager* rm) : id(0), tribalRecipe(0), homeRadius(0), homeSector(0), maxSize(0), wealthResourceGrowth(0.0), wealthResourceGrowthActive(0.0), wealthResourceGrowthActiveLimit(0), accWealthGrowth(0.0), reproductionCost(0), deathRate(0.0), resourceRate(0.0) { lastGrowth = csGetTicks(); lastDeath = csGetTicks(); lastResource = csGetTicks(); lastAdvance = csGetTicks(); eventManager = eventmngr; recipeManager = rm; }
bool Client::AllowDisconnect() { if(!GetActor() || !GetCharacterData()) return true; if(GetActor()->GetInvincibility()) return true; if(!zombie) { zombie = true; // max 3 minute timeout period zombietimeout = csGetTicks() + 3 * 60 * 1000; } else if(csGetTicks() > zombietimeout) { return true; } return allowedToDisconnect; }
PhonicEntry *NameGenerator::GetRandomEnder(bool prejoiner) { size_t i; float randval,currentsum; size_t entry_count = entries.GetSize(); csTicks timeLimit=5000; csTicks tickBegin=csGetTicks(); while ((csGetTicks() - tickBegin) < timeLimit) { randval=randomgen->Get() * end_total; currentsum=0.0f; for (i=0;i<entry_count;i++) { if (entries[i]->end_probability) { currentsum+=entries[i]->end_probability; if (randval < currentsum) { if (((entries[i]->flags & PHONIC_PREJOINER) && prejoiner) || (!(entries[i]->flags & PHONIC_PREJOINER) && !prejoiner)) { // Found the requested type return (entries[i]); } else { // Didn't find the requested type, reroll break; } } } } } // We'll return the last one here, though this can't happen return (entries[entry_count-1]); }
void PawsManager::Draw() { // First draw the main gui. if(!render2texture || true/* TODO: mainWidget->NeedsRender()*/) { if(render2texture) { graphics3D->SetRenderTarget(guiTexture); graphics3D->BeginDraw(CSDRAW_2DGRAPHICS); } mainWidget->DrawChildren(); if(render2texture) { graphics3D->FinishDraw(); graphics3D->Print(0); } } if(render2texture) { graphics3D->SetRenderTarget(0); graphics3D->BeginDraw(CSDRAW_2DGRAPHICS); graphics3D->DrawPixmap(guiTexture, 0, 0, graphics3D->GetWidth(), graphics3D->GetHeight(), 0, 0, graphics3D->GetWidth(), graphics3D->GetHeight()); // Draw all pawsobjectview next. for(size_t i=0; i<objectViews.GetSize(); ++i) { if(objectViews[i]->IsVisible()) objectViews[i]->Draw(); } } // Now everything else. if ( modalWidget != NULL ) modalWidget->Draw(); graphics2D->SetClipRect( 0,0, graphics2D->GetWidth(), graphics2D->GetHeight()); // Draw the tooltip above all other windows after 250 csTicks if (timeOver < csGetTicks() - tipDelay && mouseoverWidget) { mouseoverWidget->DrawToolTip(mouse->GetPosition().x, mouse->GetPosition().y); } if (dragDropWidget == NULL) mouse->Draw(); else dragDropWidget->Draw(); }
bool GMEventManager::CheckEvalStatus(PID PlayerID, GMEvent *Event) { if (Event->status == COMPLETED && PlayerID != Event->gmID && Event->EndTime != 0 && csGetTicks()-Event->EndTime < EVAL_LOCKOUT_TIME) { size_t PlayerIndex = GetPlayerFromEvent(PlayerID, Event); if(PlayerIndex != SIZET_NOT_FOUND) { if(Event->Player.Get(PlayerIndex).CanEvaluate) return true; } } return false; }
void Tribe::UpdateResourceRate(int amount) { csTicks now = csGetTicks(); // Calculate delta, integer types give nice rollover int delta = now - lastResource; float rate = delta/amount; float N = 0.9f; resourceRate = (1.0-N)*rate + N*resourceRate; lastResource = now; }
void Tribe::UpdateDeathRate() { csTicks now = csGetTicks(); // Calculate delta, integer types give nice rollover int delta = now - lastDeath; float rate = delta; float N = 0.9f; deathRate = (1.0-N)*rate + N*deathRate; lastDeath = now; }
bool psAttack::Attack(gemActor* attacker, gemActor* target, INVENTORY_SLOT_NUMBER slot) { psCharacter* character = attacker->GetCharacterData(); psItem* weapon = character->Inventory().GetEffectiveWeaponInSlot(slot); if(!attacker->StartAttack()) return false; float dist; { csVector3 attackerPos, targetPos; iSector* attackerSector, *targetSector; attacker->GetPosition(attackerPos, attackerSector); target->GetPosition(targetPos, targetSector); if((attacker->GetInstance() != target->GetInstance() && attacker->GetInstance() != INSTANCE_ALL && target->GetInstance() != INSTANCE_ALL) || !(EntityManager::GetSingleton().GetWorld()->WarpSpace(targetSector, attackerSector, targetPos))) { return false; } dist = sqrtf(csSquaredDist::PointPoint(targetPos, attackerPos)); } psCombatAttackGameEvent* event = new psCombatAttackGameEvent(0, this, attacker, target, slot, weapon); MathEnvironment& env(event->env); env.Define("AttackID", id); env.Define("AttackTypeID", type ? type->id : 0); env.Define("Attacker", attacker); env.Define("Target", target); env.Define("OrigTarget", target); env.Define("AttackSlot", slot); env.Define("AttackWeapon", weapon); env.Define("RelatedStatID", type ? type->related_stat : 0); env.Define("Distance", dist); csTicks delay = attackDelay ? (csTicks)round(attackDelay->Evaluate(&env)) : 0; event->triggerticks = csGetTicks() + delay; // Save the delay in the environment for other scripts to use. env.Define("Delay", delay); character->TagEquipmentObject(slot, event->id); psserver->GetEventManager()->Push(event); return true; }
bool GMEventManager::CompleteGMEvent (Client* client, PID gmID, bool byTheControllerGM) { int zero = 0; // if this GM does not have an active event, he/she can't end it. GMEvent* theEvent; int clientnum = client->GetClientNum(); if ((theEvent = GetGMEventByGM(gmID, RUNNING, zero)) == NULL) { psserver->SendSystemInfo(clientnum, "You are not running an event."); return false; } // inform players ClientConnectionSet* clientConnections = psserver->GetConnections(); Client* target; for (size_t p = 0; p < theEvent->Player.GetSize(); p++) { if ((target = clientConnections->FindPlayer(theEvent->Player[p].PlayerID))) { // psCharacter target->GetActor()->GetCharacterData()->CompleteGMEvent(false); psserver->SendSystemInfo(target->GetClientNum(), "Event '%s' complete.", theEvent->eventName.GetDataSafe()); } } // GMs psCharacter if (byTheControllerGM) client->GetActor()->GetCharacterData()->CompleteGMEvent(true); // Update description & flag the event complete if (theEvent->gmID == UNDEFINED_GMID) theEvent->eventDescription += " (No GM)"; else theEvent->eventDescription += " (" + csString(client->GetName()) + ")"; csString EscEventDescription; db->Escape(EscEventDescription, theEvent->eventDescription); db->Command("UPDATE gm_events SET status = %d, description = '%s' WHERE id = %d", COMPLETED, EscEventDescription.GetDataSafe(), theEvent->id); theEvent->status = COMPLETED; theEvent->EndTime = csGetTicks(); psserver->SendSystemInfo(clientnum, "Event '%s' complete.", theEvent->eventName.GetDataSafe()); return true; }
void WalkTestRecorder::HandleRecordedCamera (iCamera* c) { if (cfg_playrecording >= 0 && recording.GetSize () > 0) { csRecordedCamera* reccam = (csRecordedCamera*)recording[cfg_playrecording]; cfg_playrecording++; record_frame_count++; if ((size_t)cfg_playrecording >= recording.GetSize ()) { csTicks t1 = record_start_time; csTicks t2 = csGetTicks (); int num = record_frame_count; walktest->Report (CS_REPORTER_SEVERITY_NOTIFY, "End demo: %f secs to render %d frames: %f fps", (float) (t2 - t1) / 1000., num, float (num) * 1000. / (float) (t2 - t1)); csPrintf ( "End demo: %f secs to render %d frames: %f fps\n", (float) (t2 - t1) / 1000., num, float (num) * 1000. / (float) (t2 - t1)); fflush (stdout); if (cfg_playloop) cfg_playrecording = 0; else cfg_playrecording = -1; record_start_time = csGetTicks (); record_frame_count = 0; } if (reccam->sector) c->SetSector (reccam->sector); c->SetMirrored (reccam->mirror); c->GetTransform ().SetO2T (reccam->mat); c->GetTransform ().SetOrigin (reccam->vec); } }
void pawsNpcDialogWindow::Draw() { //let this dialog invisible for the time calculated to read the NPC say text //if we got a new psDialogMenuMessage we don't need to ask for a new menu (gotNewMenu) if(useBubbles && ticks != 0 && csGetTicks()-ticks > timeDelay && !gotNewMenu) { Debug1(LOG_PAWS,0,"Hiding NPC speech and asking for another set of possible questions."); speechBubble->Hide(); FindWidget("FreeBubble")->Show(); psengine->GetCmdHandler()->Execute("/npcmenu"); ticks = 0; } //printf("gotNewMenu: %d, ticks: %d timeDelay: %d\n",gotNewMenu?1:0, (csGetTicks()-ticks), timeDelay); pawsWidget::Draw(); }
NetBase::NetBase(int outqueuesize) : senders(outqueuesize) { randomgen = new csRandomGen; pipe_fd[0] = 0; pipe_fd[1] = 0; if (socklibrefcount==0 && initSocket()) ERRORHALT ("couldn't init socket library!"); socklibrefcount++; NetworkQueue.AttachNew(new NetPacketQueueRefCount(MAXQUEUESIZE)); if (!NetworkQueue) ERRORHALT("No Memory!"); ready=false; totaltransferout = 0; totaltransferin = 0; totalcountin = 0; totalcountout = 0; profs = new psNetMsgProfiles(); // Initialize the timeout to 30ms, adds 30ms of latency but gives time for packets to coalesce timeout.tv_sec = 0; timeout.tv_usec = 30000; accessPointers.msgstrings = NULL; accessPointers.msgstringshash = NULL; accessPointers.engine = NULL; logmsgfiltersetting.invert = false; logmsgfiltersetting.filterhex = true; logmsgfiltersetting.receive = false; logmsgfiltersetting.send = false; input_buffer = NULL; for(int i=0;i < NETAVGCOUNT;i++) { sendStats[i].senders = sendStats[i].messages = sendStats[i].time = 0; } for(int i =0;i < RESENDAVGCOUNT;i++) resends[i] = 0; avgIndex = resendIndex = 0; lastSendReport = csGetTicks(); }
void WalkTestRecorder::PlayRecording (bool loop) { if (cfg_playrecording == -1) { cfg_recording = -1; cfg_playrecording = 0; walktest->Report (CS_REPORTER_SEVERITY_NOTIFY, "Start playing back camera movement%s...", loop ? "" : " once"); cfg_playloop = loop; record_start_time = csGetTicks (); record_frame_count = 0; } else { cfg_playrecording = -1; walktest->Report (CS_REPORTER_SEVERITY_NOTIFY, "Stop playback."); } }
void psLinearMovement::SetDRData (bool on_ground, csVector3& pos, float yrot, iSector *sector, csVector3& vel, csVector3& worldVel, float ang_vel) { if (colldet) { colldet->SetOnGround (on_ground); } SetPosition (pos,yrot,sector); SetVelocity (vel); ClearWorldVelocity (); AddVelocity (worldVel); csVector3 rot (0.0f, ang_vel, 0.0f); SetAngularVelocity (rot); lastDRUpdate = csGetTicks (); lastClientDRUpdate = lastDRUpdate; lastClientPosition = pos; lastClientSector = sector; lastClientYrot = yrot; }
void SpellManager::HandleGlyphRequest(MsgEntry* notused, Client* client) { // FIXME: Ugly hack here as a temporary workaround for client-side issue that causes the server // to be flooded with glyph requests. Remove after all clients have been updated // to stop flooding. csTicks currentTime = csGetTicks(); // Send a glyph message maximum once per 250 ticks (0.25 seconds). if(!client->lastGlyphSend || client->lastGlyphSend + 250 < currentTime) { client->lastGlyphSend = currentTime; SendGlyphs(notused, client); } else { csString status; status.Format("Ignored glyph request message from %u.", client->GetClientNum()); if(LogCSV::GetSingletonPtr()) LogCSV::GetSingleton().Write(CSV_STATUS, status); } }
psGameEvent::psGameEvent(csTicks ticks,int offsetticks, const char* newType) { if(ticks) { triggerticks = ticks + offsetticks; //printf("event 38 ticks %d offsetticks %d triggerticks %d \n",ticks,offsetticks,triggerticks ); } else { triggerticks = csGetTicks() + offsetticks; //printf("event 43 ticks %d offsetticks %d triggerticks %d \n",ticks,offsetticks,triggerticks ); } delayticks = offsetticks; strncpy(type,newType, 31); type[31] = '\0'; id = CS::Threading::AtomicOperations::Increment(&nextid); valid = true; //printf("event 51 delayticks %d \n",delayticks ); }
bool csMovieRecorder::HandleEndFrame (iEvent& /*event*/) { if (IsRecording() && !IsPaused()) { csRef<iImage> img (csPtr<iImage> (G2D->ScreenShot ())); csTicks ticks = csGetTicks(); csTicks thisFrameTime = ticks - frameStartTime; if (!img) { Report (CS_REPORTER_SEVERITY_ERROR, "This video driver doesn't support screen capture."); Stop(); return false; } // If we're recording to a different resolution, try to scale the image if (img->GetWidth() != writer->width || img->GetHeight() != writer->height) { img = csImageManipulate::Rescale (img, writer->width, writer->height); } numFrames++; csTicks encodeTime, writeTime; unsigned char *buffer = (unsigned char *) img->GetImageData(); writer->writeFrame(buffer, encodeTime, writeTime); totalFrameTime += thisFrameTime; minFrameTime = MIN (minFrameTime, thisFrameTime); maxFrameTime = MAX (maxFrameTime, thisFrameTime); totalFrameEncodeTime += encodeTime; minFrameEncodeTime = MIN (minFrameEncodeTime, encodeTime); maxFrameEncodeTime = MAX (maxFrameEncodeTime, encodeTime); totalWriteToDiskTime += writeTime; minWriteToDiskTime = MIN (minWriteToDiskTime, writeTime); maxWriteToDiskTime = MAX (maxWriteToDiskTime, writeTime); } return false; }
void csMovieRecorder::Start(void) { SetupPlugin(); if (IsPaused()) { UnPause(); return; } if (IsRecording()) Stop(); movieFileName = recordingFile != "" ? recordingFile : captureFormat.FindNextFilename (VFS); // If the config specified 0x0, that means we use the current resolution unscaled int w = recordWidth ? recordWidth : G2D->GetWidth(); int h = recordHeight ? recordHeight : G2D->GetHeight(); numFrames = 0; totalFrameEncodeTime = totalFrameTime = totalWriteToDiskTime = 0; minFrameEncodeTime = minFrameTime = minWriteToDiskTime = (csTicks)-1; maxFrameEncodeTime = maxFrameTime = maxWriteToDiskTime = 0; movieFile = VFS->Open (movieFileName, VFS_FILE_WRITE | VFS_FILE_UNCOMPRESSED); if (!movieFile) { Report (CS_REPORTER_SEVERITY_WARNING, "Couldn't open file %s for recording", CS::Quote::Single (movieFileName.GetData())); return; } fakeTicksPerFrame = (1000 / frameRate); ffakeClockTicks = fakeClockTicks; frameStartTime = csGetTicks(); writer = new NuppelWriter(w, h, &WriterCallback, this, frameRate, rtjQuality, useRTJpeg, useLZO, useRGB); Report (CS_REPORTER_SEVERITY_NOTIFY, "Video recorder started - %s", movieFileName.GetData()); }
void psMovementManager::LockMoves(bool v) { locked = v; if (!actor) return; //we had a special event we need to unset stationary in case so the client //queries the server on the status at least one time. actor->stationary = false; actor->lastDRUpdateTime = csGetTicks(); if (v) { StopAllMovement(); } else { actor->Movement().ResetGravity(); } }
void psClientDR::CheckDeadReckoningUpdate() { static float prevVelY = 0; // vertical velocity of the character when this method was last called csVector3 vel; // current velocity of the character bool beganFalling; if ( !celclient->GetMainPlayer() ) { return; } lastupdate = csGetTicks(); if(celclient->IsUnresSector(celclient->GetMainPlayer()->GetSector())) return; // Main actor still in unresolved sector vel = celclient->GetMainPlayer()->GetVelocity(); beganFalling = (prevVelY>=0 && vel.y<0); prevVelY = vel.y; uint8_t priority; if (! (celclient->GetMainPlayer()->NeedDRUpdate(priority) || beganFalling) ) { // no need to send new packet, real position is as calculated return; } if (!msgstrings) { Error1("msgstrings not received, cannot handle DR"); return; } celclient->GetMainPlayer()->SendDRUpdate(priority,msgstrings); return; }
void G2DTestSystemDriver::EnterState (appState newstate, int arg) { state [state_sptr++] = newstate; switch (newstate) { case stPause: timer = csGetTicks () + arg; break; case stTestLinePerf: lastkey2 = 0; break; case stTestTextDraw: lastkey3 = 0; break; case stTestTextDraw2: lastkey4 = 0; break; case stPixelClipTest: lastkey5 = 0; break; case stLineClipTest: lastkey6 = 0; break; case stBoxClipTest: lastkey7 = 0; break; case stFontClipTest: lastkey8 = 0; break; case stCustomCursor: lastkey9 = 0; break; case stWaitKey: lastkey = 0; break; default: break; } }
csTicks csBlobViewPort::InitiateScroll (int newx, int newy) { if (newx == scrollx && newy == scrolly) return 0; start_scrollx = float (scrollx); start_scrolly = float (scrolly); end_scrollx = float (newx); end_scrolly = float (newy); float dx = end_scrollx - start_scrollx; float dy = end_scrolly - start_scrolly; float dist = sqrt (dx * dx + dy * dy); //scroll_start_time = float (mgr->vc->GetCurrentTicks ()); scroll_start_time = float (csGetTicks ()); if (dist <= 200) scroll_total_time = dist; else if (dist < 500) scroll_total_time = dist/2.0f; else scroll_total_time = dist/4.0f; scroll_total_time *= scrollspeed; return csTicks (scroll_total_time); }
SoundSystemManager::SoundSystemManager (iObjectRegistry* objectReg) { // Initialised to false to make sure it is .. Initialised = false; // Create a new SoundSystem and SoundData Instance soundSystem = new SoundSystem; soundData = new SoundData; // SoundControls used by GUI and EFFECTS - FIXME (to be removed) mainSndCtrl = GetSoundControl(); guiSndCtrl = GetSoundControl(); effectSndCtrl = GetSoundControl(); if (soundSystem->Initialize (objectReg) && soundData->Initialize (objectReg)) { // soundLib = cfg->GetStr("PlaneShift.Sound.SoundLib", "/planeshift/art/soundlib.xml"); /* FIXME HARDCODED*/ // also FIXME what if soundlib.xml doesnt exist? soundData->LoadSoundLib ("/planeshift/art/soundlib.xml", objectReg); LastUpdateTime = csGetTicks(); Initialised = true; } }
void Client::FloodControl(uint8_t chatType, const csString & newMessage, const csString & recipient) { int matches = 0; floodHistory[nextFloodHistoryIndex] = FloodBuffRow(chatType, newMessage, recipient, csGetTicks()); nextFloodHistoryIndex = (nextFloodHistoryIndex + 1) % floodMax; // Count occurances of this new message in the flood history. for (int i = 0; i < floodMax; i++) { if (csGetTicks() - floodHistory[i].ticks < floodForgiveTime && floodHistory[i].chatType == chatType && floodHistory[i].text == newMessage && floodHistory[i].recipient == recipient) matches++; } if (matches >= floodMax) { SetMute(true); psserver->SendSystemError(clientnum, "BAM! Muted."); } else if (matches >= floodWarn) { psserver->SendSystemError(clientnum, "Flood warning. Stop or you will be muted."); } }