//------------------------------------------------------------------------------ // Purpose : Itterate through the panels and make sure none have become // unstable // Input : // Output : //------------------------------------------------------------------------------ void CBreakableSurface::BreakThink(void) { // Don't calculate support if I'm tile if (m_nSurfaceType == SHATTERSURFACE_TILE) { return; } // ----------------------- // Recalculate all support // ----------------------- int w; float flSupport[MAX_NUM_PANELS][MAX_NUM_PANELS]; for (w=0;w<m_nNumWide;w++) { for (int h=0;h<m_nNumHigh;h++) { if (!IsBroken(w,h)) { flSupport[w][h] = RecalcSupport(w,h); } } } // ---------------------------------------------------- // Set support and break inadequately supported panes // ---------------------------------------------------- float flBreakValue = WINDOW_BREAK_SUPPORT*(m_nFragility/100.0); for (w=0;w<m_nNumWide;w++) { for (int h=0;h<m_nNumHigh;h++) { if (!IsBroken(w,h)) { SetSupport( w, h, flSupport[w][h]/WINDOW_MAX_SUPPORT ); if (m_flSupport[w][h] < flBreakValue) { // Occasionaly drop a pane if (random->RandomInt(0,1)) { DropPane(w,h); } // Otherwise just shatter the glass else { ShatterPane(w,h,vec3_origin,vec3_origin); } SetNextThink( gpGlobals->curtime ); } } } } }
/* ================ idBrittleFracture::Event_Touch ================ */ void idBrittleFracture::Event_Touch( idEntity* other, trace_t* trace ) { idVec3 point, impulse; // Let the server handle this, clients dont' predict it if( common->IsClient() ) { return; } if( !IsBroken() ) { return; } if( trace->c.id < 0 || trace->c.id >= shards.Num() ) { return; } point = shards[trace->c.id]->clipModel->GetOrigin(); impulse = other->GetPhysics()->GetLinearVelocity() * other->GetPhysics()->GetMass(); Shatter( point, impulse, gameLocal.time ); }
//------------------------------------------------------------------------------ // Purpose : Drop a window pane entity // Input : // Output : //------------------------------------------------------------------------------ void CBreakableSurface::DropPane(int nWidth, int nHeight) { // Check parameter range if (nWidth < 0 || nWidth >= m_nNumWide) return; if (nHeight < 0 || nHeight >= m_nNumHigh) return; if (!IsBroken(nWidth,nHeight)) { BreakPane(nWidth,nHeight); QAngle vAngles; VectorAngles(-1*m_vNormal,vAngles); Vector vWidthDir,vHeightDir; AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); Vector vBreakPos = m_vCorner + (nWidth*vWidthDir*m_flPanelWidth) + (nHeight*vHeightDir*m_flPanelHeight); CreateShards(vBreakPos, vAngles, vec3_origin, vec3_origin, WINDOW_PANEL_SIZE, WINDOW_PANEL_SIZE, WINDOW_SMALL_SHARD_SIZE); DamageSound(); CWindowPane *pPane = CWindowPane::CreateWindowPane(vBreakPos, vAngles); if (pPane) { pPane->SetLocalAngularVelocity( RandomAngle(-120,120) ); } } }
/* ================ idBrittleFracture::Shatter ================ */ void idBrittleFracture::Shatter( const idVec3 &point, const idVec3 &impulse, const int time ) { int i; idVec3 dir; shard_t *shard; float m; if ( gameLocal.isServer ) { idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; msg.Init( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); msg.WriteFloat( point[0] ); msg.WriteFloat( point[1] ); msg.WriteFloat( point[2] ); msg.WriteFloat( impulse[0] ); msg.WriteFloat( impulse[1] ); msg.WriteFloat( impulse[2] ); ServerSendEvent( EVENT_SHATTER, &msg, true, -1 ); } if ( time > ( gameLocal.time - SHARD_ALIVE_TIME ) ) { StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL ); } if ( !IsBroken() ) { Break(); } if ( fxFracture.Length() ) { idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true ); } dir = impulse; m = dir.Normalize(); for ( i = 0; i < shards.Num(); i++ ) { shard = shards[i]; if ( shard->droppedTime != -1 ) { continue; } if ( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) { continue; } DropShard( shard, point, dir, m, time ); } DropFloatingIslands( point, impulse, time ); //trigger it. if (!firedTargets) { firedTargets = true; ActivateTargets(this); } }
/* ================ idBrittleFracture::Event_Touch ================ */ void idBrittleFracture::Event_Touch( idEntity *other, trace_t *trace ) { idVec3 point, impulse; if( !IsBroken() ) { return; } if( trace->c.id < 0 || trace->c.id >= shards.Num() ) { return; } point = shards[trace->c.id]->clipModel->GetOrigin(); impulse = other->GetPhysics()->GetLinearVelocity() * other->GetPhysics()->GetMass(); Shatter( point, impulse, gameLocal.time ); }
/* ================ idBrittleFracture::UpdateSoundLoss (Dark Mod ) ================ */ void idBrittleFracture::UpdateSoundLoss( void ) { float SetVal( 0.0f ); if( !m_AreaPortal ) { return; } if( IsBroken() ) { SetVal = spawnArgs.GetFloat( "loss_broken", "0.0" ); } else { SetVal = spawnArgs.GetFloat( "loss_unbroken", "15.0" ); } gameLocal.m_sndProp->SetPortalAILoss( m_AreaPortal, SetVal + m_lossBaseAI ); // grayman #3042 - add base loss from portal entities gameLocal.m_sndProp->SetPortalPlayerLoss( m_AreaPortal, SetVal + m_lossBasePlayer ); // grayman #3042 - add base loss from portal entities }
// delete any nodes which have no route to start node void GramSubN::DeleteUnlinked() { if (int n = IsBroken(FALSE)){ HRError(10721,"AGram::DeleteUnlinked - subnet not valid(%d)",n); ATK_Error(10721); } NodeIterator ni=nodes.begin(); while( ni!=nodes.end()){ if((*ni)->seen) ++ni; else { delete *ni; ni=nodes.erase(ni); } } }
/* ================ c4tnt: now fractures can be broken at start idBrittleFracture::StartBroken ================ */ void idBrittleFracture::StartBroken( const float part, float disperse) { int i, counter; shard_t *shard; shard_t *shardorg; idVec3 point; if ( disperse > 0.9) disperse = 0.9f; if ( !IsBroken() ) { Break(); } counter = shards.Num() * part; if ( counter > shards.Num()) counter = shards.Num(); while (counter > 0) { for ( i = 0; i < shards.Num(); i++ ) { shardorg = shards[i]; if ( shardorg->droppedTime != -1 ) { continue; } if (gameLocal.random.RandomFloat() > disperse) { counter--; point = shardorg->clipModel->GetOrigin(); for ( i = 0; i < shards.Num(); i++ ) { shard = shards[i]; if ( shard->droppedTime != -1 || shard == shardorg) { continue; } if ( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) { continue; } counter--; DropShard( shard ); } DropShard( shardorg ); DropFloatingIslands( &counter ); } } } }
//------------------------------------------------------------------------------ // Purpose : Break a panel // Input : // Output : //------------------------------------------------------------------------------ bool CBreakableSurface::ShatterPane(int nWidth, int nHeight, const Vector &vForce, const Vector &vForcePos) { // Check parameter range if (nWidth < 0 || nWidth >= m_nNumWide) return false; if (nHeight < 0 || nHeight >= m_nNumHigh) return false; if ( IsBroken(nWidth,nHeight) ) return false; BreakPane(nWidth,nHeight); QAngle vAngles; VectorAngles(-1*m_vNormal,vAngles); Vector vWidthDir,vHeightDir; AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); Vector vBreakPos = m_vCorner + (nWidth*vWidthDir*m_flPanelWidth) + (nHeight*vHeightDir*m_flPanelHeight); CreateShards(vBreakPos, vAngles,vForce, vForcePos, m_flPanelWidth, m_flPanelHeight, WINDOW_SMALL_SHARD_SIZE); DamageSound(); return true; }
/* ================ idBrittleFracture::Shatter ================ */ void idBrittleFracture::Shatter( const idVec3& point, const idVec3& impulse, const int time ) { int i; idVec3 dir; shard_t* shard; float m; if( common->IsServer() ) { idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; msg.InitWrite( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); msg.WriteFloat( point[0] ); msg.WriteFloat( point[1] ); msg.WriteFloat( point[2] ); msg.WriteFloat( impulse[0] ); msg.WriteFloat( impulse[1] ); msg.WriteFloat( impulse[2] ); ServerSendEvent( EVENT_SHATTER, &msg, true ); } // Store off the event so we can rebuilt the object if we reload a savegame fractureEvent_s fractureEvent; fractureEvent.eventType = EVENT_SHATTER; fractureEvent.point = point; fractureEvent.vector = impulse; storedEvents.Append( fractureEvent ); if( time > ( gameLocal.time - SHARD_ALIVE_TIME ) ) { StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL ); } if( !IsBroken() ) { Break(); } if( fxFracture.Length() ) { idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true ); } dir = impulse; m = dir.Normalize(); for( i = 0; i < shards.Num(); i++ ) { shard = shards[i]; if( shard->droppedTime != -1 ) { continue; } if( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) { continue; } DropShard( shard, point, dir, m, time ); } DropFloatingIslands( point, impulse, time ); }
// not from interface void nsHtml5Parser::ParseUntilBlocked() { if (mBlocked || mExecutor->IsComplete() || mExecutor->IsBroken()) { return; } NS_ASSERTION(mExecutor->HasStarted(), "Bad life cycle."); NS_ASSERTION(!mInDocumentWrite, "ParseUntilBlocked entered while in doc.write!"); mDocWriteSpeculatorActive = false; for (;;) { if (!mFirstBuffer->hasMore()) { if (mFirstBuffer == mLastBuffer) { if (mExecutor->IsComplete()) { // something like cache manisfests stopped the parse in mid-flight return; } if (mDocumentClosed) { NS_ASSERTION(!mStreamParser, "This should only happen with script-created parser."); mTokenizer->eof(); mTreeBuilder->StreamEnded(); mTreeBuilder->Flush(); mExecutor->FlushDocumentWrite(); mTokenizer->end(); return; } // never release the last buffer. NS_ASSERTION(!mLastBuffer->getStart() && !mLastBuffer->getEnd(), "Sentinel buffer had its indeces changed."); if (mStreamParser) { if (mReturnToStreamParserPermitted && !mExecutor->IsScriptExecuting()) { mTreeBuilder->Flush(); mReturnToStreamParserPermitted = false; mStreamParser->ContinueAfterScripts(mTokenizer, mTreeBuilder, mLastWasCR); } } else { // Script-created parser mTreeBuilder->Flush(); // No need to flush the executor, because the executor is already // in a flush NS_ASSERTION(mExecutor->IsInFlushLoop(), "How did we come here without being in the flush loop?"); } return; // no more data for now but expecting more } mFirstBuffer = mFirstBuffer->next; continue; } if (mBlocked || mExecutor->IsComplete()) { return; } // now we have a non-empty buffer mFirstBuffer->adjust(mLastWasCR); mLastWasCR = false; if (mFirstBuffer->hasMore()) { bool inRootContext = (!mStreamParser && !mFirstBuffer->key); if (inRootContext) { mTokenizer->setLineNumber(mRootContextLineNumber); } mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer); if (inRootContext) { mRootContextLineNumber = mTokenizer->getLineNumber(); } if (mTreeBuilder->HasScript()) { mTreeBuilder->Flush(); mExecutor->FlushDocumentWrite(); } if (mBlocked) { return; } } continue; } }
NS_IMETHODIMP nsHtml5Parser::Parse(const nsAString& aSourceBuffer, void* aKey, const nsACString& aContentType, bool aLastCall, nsDTDMode aMode) // ignored { if (mExecutor->IsBroken()) { return NS_ERROR_OUT_OF_MEMORY; } if (aSourceBuffer.Length() > PR_INT32_MAX) { mExecutor->MarkAsBroken(); return NS_ERROR_OUT_OF_MEMORY; } // Maintain a reference to ourselves so we don't go away // till we're completely done. The old parser grips itself in this method. nsCOMPtr<nsIParser> kungFuDeathGrip(this); // Gripping the other objects just in case, since the other old grip // required grips to these, too. nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser); nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor); if (!mExecutor->HasStarted()) { NS_ASSERTION(!mStreamParser, "Had stream parser but document.write started life cycle."); // This is the first document.write() on a document.open()ed document mExecutor->SetParser(this); mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled()); mTokenizer->start(); mExecutor->Start(); if (!aContentType.EqualsLiteral("text/html")) { mTreeBuilder->StartPlainText(); mTokenizer->StartPlainText(); } /* * If you move the following line, be very careful not to cause * WillBuildModel to be called before the document has had its * script global object set. */ mExecutor->WillBuildModel(eDTDMode_unknown); } // Return early if the parser has processed EOF if (mExecutor->IsComplete()) { return NS_OK; } if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) { // document.close() NS_ASSERTION(!mStreamParser, "Had stream parser but got document.close()."); if (mDocumentClosed) { // already closed return NS_OK; } mDocumentClosed = true; if (!mBlocked && !mInDocumentWrite) { ParseUntilBlocked(); } return NS_OK; } // If we got this far, we are dealing with a document.write or // document.writeln call--not document.close(). NS_ASSERTION(IsInsertionPointDefined(), "Doc.write reached parser with undefined insertion point."); NS_ASSERTION(!(mStreamParser && !aKey), "Got a null key in a non-script-created parser"); // XXX is this optimization bogus? if (aSourceBuffer.IsEmpty()) { return NS_OK; } // This guard is here to prevent document.close from tokenizing synchronously // while a document.write (that wrote the script that called document.close!) // is still on the call stack. mozilla::AutoRestore<bool> guard(mInDocumentWrite); mInDocumentWrite = true; // The script is identified by aKey. If there's nothing in the buffer // chain for that key, we'll insert at the head of the queue. // When the script leaves something in the queue, a zero-length // key-holder "buffer" is inserted in the queue. If the same script // leaves something in the chain again, it will be inserted immediately // before the old key holder belonging to the same script. // // We don't do the actual data insertion yet in the hope that the data gets // tokenized and there no data or less data to copy to the heap after // tokenization. Also, this way, we avoid inserting one empty data buffer // per document.write, which matters for performance when the parser isn't // blocked and a badly-authored script calls document.write() once per // input character. (As seen in a benchmark!) // // The insertion into the input stream happens conceptually before anything // gets tokenized. To make sure multi-level document.write works right, // it's necessary to establish the location of our parser key up front // in case this is the first write with this key. // // In a document.open() case, the first write level has a null key, so that // case is handled separately, because normal buffers containing data // have null keys. // These don't need to be owning references, because they always point to // the buffer queue and buffers can't be removed from the buffer queue // before document.write() returns. The buffer queue clean-up happens the // next time ParseUntilBlocked() is called. // However, they are made owning just in case the reasoning above is flawed // and a flaw would lead to worse problems with plain pointers. If this // turns out to be a perf problem, it's worthwhile to consider making // prevSearchbuf a plain pointer again. nsRefPtr<nsHtml5OwningUTF16Buffer> prevSearchBuf; nsRefPtr<nsHtml5OwningUTF16Buffer> firstLevelMarker; if (aKey) { if (mFirstBuffer == mLastBuffer) { nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey); keyHolder->next = mLastBuffer; mFirstBuffer = keyHolder; } else if (mFirstBuffer->key != aKey) { prevSearchBuf = mFirstBuffer; for (;;) { if (prevSearchBuf->next == mLastBuffer) { // key was not found nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey); keyHolder->next = mFirstBuffer; mFirstBuffer = keyHolder; prevSearchBuf = nsnull; break; } if (prevSearchBuf->next->key == aKey) { // found a key holder break; } prevSearchBuf = prevSearchBuf->next; } } // else mFirstBuffer is the keyholder // prevSearchBuf is the previous buffer before the keyholder or null if // there isn't one. } else { // We have a first-level write in the document.open() case. We insert // before mLastBuffer. We need to put a marker there, because otherwise // additional document.writes from nested event loops would insert in the // wrong place. Sigh. firstLevelMarker = new nsHtml5OwningUTF16Buffer((void*)nsnull); if (mFirstBuffer == mLastBuffer) { firstLevelMarker->next = mLastBuffer; mFirstBuffer = firstLevelMarker; } else { prevSearchBuf = mFirstBuffer; while (prevSearchBuf->next != mLastBuffer) { prevSearchBuf = prevSearchBuf->next; } firstLevelMarker->next = mLastBuffer; prevSearchBuf->next = firstLevelMarker; } } nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer); while (!mBlocked && stackBuffer.hasMore()) { stackBuffer.adjust(mLastWasCR); mLastWasCR = false; if (stackBuffer.hasMore()) { PRInt32 lineNumberSave; bool inRootContext = (!mStreamParser && !aKey); if (inRootContext) { mTokenizer->setLineNumber(mRootContextLineNumber); } else { // we aren't the root context, so save the line number on the // *stack* so that we can restore it. lineNumberSave = mTokenizer->getLineNumber(); } mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer); if (inRootContext) { mRootContextLineNumber = mTokenizer->getLineNumber(); } else { mTokenizer->setLineNumber(lineNumberSave); } if (mTreeBuilder->HasScript()) { mTreeBuilder->Flush(); // Move ops to the executor mExecutor->FlushDocumentWrite(); // run the ops // Flushing tree ops can cause all sorts of things. // Return early if the parser got terminated. if (mExecutor->IsComplete()) { return NS_OK; } } // Ignore suspension requests } } nsRefPtr<nsHtml5OwningUTF16Buffer> heapBuffer; if (stackBuffer.hasMore()) { // The buffer wasn't tokenized to completion. Create a copy of the tail // on the heap. heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer(); if (!heapBuffer) { // Allocation failed. The parser is now broken. mExecutor->MarkAsBroken(); return NS_ERROR_OUT_OF_MEMORY; } } if (heapBuffer) { // We have something to insert before the keyholder holding in the non-null // aKey case and we have something to swap into firstLevelMarker in the // null aKey case. if (aKey) { NS_ASSERTION(mFirstBuffer != mLastBuffer, "Where's the keyholder?"); // the key holder is still somewhere further down the list from // prevSearchBuf (which may be null) if (mFirstBuffer->key == aKey) { NS_ASSERTION(!prevSearchBuf, "Non-null prevSearchBuf when mFirstBuffer is the key holder?"); heapBuffer->next = mFirstBuffer; mFirstBuffer = heapBuffer; } else { if (!prevSearchBuf) { prevSearchBuf = mFirstBuffer; } // We created a key holder earlier, so we will find it without walking // past the end of the list. while (prevSearchBuf->next->key != aKey) { prevSearchBuf = prevSearchBuf->next; } heapBuffer->next = prevSearchBuf->next; prevSearchBuf->next = heapBuffer; } } else { NS_ASSERTION(firstLevelMarker, "How come we don't have a marker."); firstLevelMarker->Swap(heapBuffer); } } if (!mBlocked) { // buffer was tokenized to completion NS_ASSERTION(!stackBuffer.hasMore(), "Buffer wasn't tokenized to completion?"); // Scripting semantics require a forced tree builder flush here mTreeBuilder->Flush(); // Move ops to the executor mExecutor->FlushDocumentWrite(); // run the ops } else if (stackBuffer.hasMore()) { // The buffer wasn't tokenized to completion. Tokenize the untokenized // content in order to preload stuff. This content will be retokenized // later for normal parsing. if (!mDocWriteSpeculatorActive) { mDocWriteSpeculatorActive = true; if (!mDocWriteSpeculativeTreeBuilder) { // Lazily initialize if uninitialized mDocWriteSpeculativeTreeBuilder = new nsHtml5TreeBuilder(nsnull, mExecutor->GetStage()); mDocWriteSpeculativeTreeBuilder->setScriptingEnabled( mTreeBuilder->isScriptingEnabled()); mDocWriteSpeculativeTokenizer = new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder, false); mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable); mDocWriteSpeculativeTokenizer->start(); } mDocWriteSpeculativeTokenizer->resetToDataState(); mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable); mDocWriteSpeculativeLastWasCR = false; } // Note that with multilevel document.write if we didn't just activate the // speculator, it's possible that the speculator is now in the wrong state. // That's OK for the sake of simplicity. The worst that can happen is // that the speculative loads aren't exactly right. The content will be // reparsed anyway for non-preload purposes. // The buffer position for subsequent non-speculative parsing now lives // in heapBuffer, so it's ok to let the buffer position of stackBuffer // to be overwritten and not restored below. while (stackBuffer.hasMore()) { stackBuffer.adjust(mDocWriteSpeculativeLastWasCR); if (stackBuffer.hasMore()) { mDocWriteSpeculativeLastWasCR = mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer); } } mDocWriteSpeculativeTreeBuilder->Flush(); mDocWriteSpeculativeTreeBuilder->DropHandles(); mExecutor->FlushSpeculativeLoads(); } return NS_OK; }
// read HTK subnet definition and create corresponding subnet GramSubN::GramSubN(Source *src) { char nbuf[132],vbuf[132],buf[32],*ptr,ntype,del; int i,n,st,en,nl=0, nn=0; float prob; Boolean isOk = TRUE; try{ name = "!!MAIN!!"; // if sublat it will be overwritten with HTK name entry = NULL; exit = NULL; refcount = 0; // read the header info while((ptr=GetNextFieldName(nbuf,&del,src))) { if (nbuf[0]=='\n') { if (nl != 0 && nn != 0) break; } else if (strlen(ptr)==1) { ntype=*ptr; switch(ntype) { case 'N': nn=GetIntField('N',del,vbuf,src); break; case 'L': nl=GetIntField('L',del,vbuf,src); break; default: GetFieldValue(0,src); break; } } else { if (strcmp(ptr,"SUBLAT") == 0) GetFieldValue(vbuf,src),name=vbuf; else GetFieldValue(NULL,src); } } if (feof(src->f)) return; // No main network // read the node and link defs vector<GramNode *> nodemap(nn); string nodename,tag; NodeKind kind; for (i=0; i<nn; i++) nodemap[i] = NULL; do { if ((ptr=GetNextFieldName(nbuf,&del,src)) == NULL) break; /* Recognised line types have only one character names */ if (strlen(ptr)==1) ntype=*ptr; else ntype=0; if (ntype == '.') { ptr = NULL; break; } switch(ntype) { case '\n': break; case 'I': n=GetIntField('I',del,vbuf,src); if (n < 0 || n >= nn){ HRError(10723,"AGram: node %d is missing",n); throw ATK_Error(10723); } if (nodemap[n] != NULL){ HRError(10724,"AGram: multiple defs for node %d",n); throw ATK_Error(10724); } nodename=""; tag=""; kind = UnknNode; while((ptr=GetNextFieldName(nbuf,&del,src)) != NULL) { if (nbuf[0]=='\n') break; else { if (strlen(ptr)>=1) ntype=*ptr; else ntype=0; switch(ntype) { case 'W': GetFieldValue(vbuf,src); if (strcmp(vbuf,"!NULL")==0) kind = NullNode; else { nodename = vbuf; kind = WordNode; } break; case 's': GetFieldValue(vbuf,src); tag = vbuf; break; case 'L': GetFieldValue(vbuf,src); nodename = vbuf; kind = CallNode; break; default: GetFieldValue(0,src); break; } } } if (kind == UnknNode){ HRError(10725,"AGram: node %d not fully defined",n); throw ATK_Error(10725); } if (kind==NullNode) {sprintf(buf,"%d",n); nodename=buf;} nodemap[n] = new GramNode(kind,nodename,tag); nodes.push_back(nodemap[n]); break; case 'J': n=GetIntField('I',del,vbuf,src); if (n<0 || n>=nl){ HRError(10726,"AGram: link %d is not possible",n); throw ATK_Error(10726); } st = en = -1; prob=0.0; while ((ptr=GetNextFieldName(nbuf,&del,src))) { if (nbuf[0]=='\n') break; else { if (strlen(ptr)>=1) ntype=*ptr; else ntype=0; switch(ntype) { case 'S': st=GetIntField('S',del,vbuf,src); if (st<0 || st>=nn){ HRError(10727,"AGram: start node %d out of range",st); throw ATK_Error(10727); } break; case 'E': en=GetIntField('E',del,vbuf,src); if (en<0 || en>=nn){ HRError(10727,"AGram: end node %d out of range",en); throw ATK_Error(10727); } break; case 'l': prob=float(GetFltField('l',del,vbuf,src)); break; default: GetFieldValue(0,src); break; } } } if (st<0 || en <0){ HRError(10728,"AGram: incomplete link spec (%d to %d)",st,en); throw ATK_Error(10728); } if (nodemap[st]==NULL){ HRError(10729,"AGram: start node %d undefined",st); throw ATK_Error(10729); } if (nodemap[en]==NULL){ HRError(10729,"AGram: end node %d undefined",en); throw ATK_Error(10729); } AddLink(nodemap[st],nodemap[en],prob); break; default: GetFieldValue(0,src); while ((ptr=GetNextFieldName(nbuf,&del,src))) { if (nbuf[0]=='\n') break; else GetFieldValue(0,src); } break; } }while(ptr != NULL); // set end points SetEnds(); // finally check that all is well n = IsBroken(TRUE); if (n != 0){ switch(n){ case 1: HRError(10729,"AGram: entry/exit node missing"); break; case 2: HRError(10729,"AGram: entry node has predecessors"); break; case 3: HRError(10729,"AGram: exit node has successors"); break; case 4: HRError(10729,"AGram: no path from entry to exit"); break; case 5: HRError(10729,"AGram: unreachable nodes"); break; } throw ATK_Error(10729); } } catch (ATK_Error e){ HRError(e.i,"AGram: error detected in subnet %s",name.c_str()); throw e; } }
NS_IMETHODIMP nsHtml5Parser::Parse(const nsAString& aSourceBuffer, void* aKey, const nsACString& aContentType, // ignored bool aLastCall, nsDTDMode aMode) // ignored { NS_PRECONDITION(!mExecutor->IsFragmentMode(), "Document.write called in fragment mode!"); if (mExecutor->IsBroken()) { return NS_ERROR_OUT_OF_MEMORY; } if (aSourceBuffer.Length() > PR_INT32_MAX) { mExecutor->MarkAsBroken(); return NS_ERROR_OUT_OF_MEMORY; } // Maintain a reference to ourselves so we don't go away // till we're completely done. The old parser grips itself in this method. nsCOMPtr<nsIParser> kungFuDeathGrip(this); // Gripping the other objects just in case, since the other old grip // required grips to these, too. nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser); nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor); if (!mExecutor->HasStarted()) { NS_ASSERTION(!mStreamParser, "Had stream parser but document.write started life cycle."); // This is the first document.write() on a document.open()ed document mExecutor->SetParser(this); mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled()); mTokenizer->start(); mExecutor->Start(); /* * If you move the following line, be very careful not to cause * WillBuildModel to be called before the document has had its * script global object set. */ mExecutor->WillBuildModel(eDTDMode_unknown); } // Return early if the parser has processed EOF if (mExecutor->IsComplete()) { return NS_OK; } if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) { // document.close() NS_ASSERTION(!mStreamParser, "Had stream parser but got document.close()."); mDocumentClosed = true; if (!mBlocked) { ParseUntilBlocked(); } return NS_OK; } NS_ASSERTION(IsInsertionPointDefined(), "Doc.write reached parser with undefined insertion point."); NS_ASSERTION(!(mStreamParser && !aKey), "Got a null key in a non-script-created parser"); if (aSourceBuffer.IsEmpty()) { return NS_OK; } nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer); while (!mBlocked && stackBuffer.hasMore()) { stackBuffer.adjust(mLastWasCR); mLastWasCR = false; if (stackBuffer.hasMore()) { PRInt32 lineNumberSave; bool inRootContext = (!mStreamParser && (aKey == mRootContextKey)); if (inRootContext) { mTokenizer->setLineNumber(mRootContextLineNumber); } else { // we aren't the root context, so save the line number on the // *stack* so that we can restore it. lineNumberSave = mTokenizer->getLineNumber(); } mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer); if (inRootContext) { mRootContextLineNumber = mTokenizer->getLineNumber(); } else { mTokenizer->setLineNumber(lineNumberSave); } if (mTreeBuilder->HasScript()) { mTreeBuilder->Flush(); // Move ops to the executor mExecutor->FlushDocumentWrite(); // run the ops } // Ignore suspension requests } } nsRefPtr<nsHtml5OwningUTF16Buffer> heapBuffer; if (stackBuffer.hasMore()) { // The buffer wasn't tokenized to completion. Create a copy of the tail // on the heap. heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer(); if (!heapBuffer) { // Allocation failed. The parser is now broken. mExecutor->MarkAsBroken(); return NS_ERROR_OUT_OF_MEMORY; } } // The buffer is inserted to the stream here in case it won't be parsed // to completion. // The script is identified by aKey. If there's nothing in the buffer // chain for that key, we'll insert at the head of the queue. // When the script leaves something in the queue, a zero-length // key-holder "buffer" is inserted in the queue. If the same script // leaves something in the chain again, it will be inserted immediately // before the old key holder belonging to the same script. nsHtml5OwningUTF16Buffer* prevSearchBuf = nsnull; nsHtml5OwningUTF16Buffer* searchBuf = mFirstBuffer; // after document.open, the first level of document.write has null key if (aKey) { while (searchBuf != mLastBuffer) { if (searchBuf->key == aKey) { // found a key holder // now insert the new buffer between the previous buffer // and the key holder if we have a buffer left. if (heapBuffer) { heapBuffer->next = searchBuf; if (prevSearchBuf) { prevSearchBuf->next = heapBuffer; } else { mFirstBuffer = heapBuffer; } } break; } prevSearchBuf = searchBuf; searchBuf = searchBuf->next; } if (searchBuf == mLastBuffer) { // key was not found nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey); keyHolder->next = mFirstBuffer; if (heapBuffer) { heapBuffer->next = keyHolder; mFirstBuffer = heapBuffer; } else { mFirstBuffer = keyHolder; } } } else if (heapBuffer) { // we have a first level document.write after document.open() // insert immediately before mLastBuffer while (searchBuf != mLastBuffer) { prevSearchBuf = searchBuf; searchBuf = searchBuf->next; } heapBuffer->next = mLastBuffer; if (prevSearchBuf) { prevSearchBuf->next = heapBuffer; } else { mFirstBuffer = heapBuffer; } } if (!mBlocked) { // buffer was tokenized to completion NS_ASSERTION(!stackBuffer.hasMore(), "Buffer wasn't tokenized to completion?"); // Scripting semantics require a forced tree builder flush here mTreeBuilder->Flush(); // Move ops to the executor mExecutor->FlushDocumentWrite(); // run the ops } else if (stackBuffer.hasMore()) { // The buffer wasn't tokenized to completion. Tokenize the untokenized // content in order to preload stuff. This content will be retokenized // later for normal parsing. if (!mDocWriteSpeculatorActive) { mDocWriteSpeculatorActive = true; if (!mDocWriteSpeculativeTreeBuilder) { // Lazily initialize if uninitialized mDocWriteSpeculativeTreeBuilder = new nsHtml5TreeBuilder(nsnull, mExecutor->GetStage()); mDocWriteSpeculativeTreeBuilder->setScriptingEnabled( mTreeBuilder->isScriptingEnabled()); mDocWriteSpeculativeTokenizer = new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder); mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable); mDocWriteSpeculativeTokenizer->start(); } mDocWriteSpeculativeTokenizer->resetToDataState(); mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable); mDocWriteSpeculativeLastWasCR = false; } // Note that with multilevel document.write if we didn't just activate the // speculator, it's possible that the speculator is now in the wrong state. // That's OK for the sake of simplicity. The worst that can happen is // that the speculative loads aren't exactly right. The content will be // reparsed anyway for non-preload purposes. // The buffer position for subsequent non-speculative parsing now lives // in heapBuffer, so it's ok to let the buffer position of stackBuffer // to be overwritten and not restored below. while (stackBuffer.hasMore()) { stackBuffer.adjust(mDocWriteSpeculativeLastWasCR); if (stackBuffer.hasMore()) { mDocWriteSpeculativeLastWasCR = mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer); } } mDocWriteSpeculativeTreeBuilder->Flush(); mDocWriteSpeculativeTreeBuilder->DropHandles(); mExecutor->FlushSpeculativeLoads(); } return NS_OK; }
//------------------------------------------------------------------------------ // Purpose: Accepts damage and breaks if health drops below zero. //------------------------------------------------------------------------------ void CBreakableSurface::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ) { //============================================================================= // HPE_BEGIN: // [dwenger] Window break stat tracking //============================================================================= // Make sure this pane has not already been shattered bool bWasBroken = m_bIsBroken; //============================================================================= // HPE_END //============================================================================= // Decrease health m_iHealth -= info.GetDamage(); m_OnHealthChanged.Set( m_iHealth, info.GetAttacker(), this ); // If I'm not broken yet, break me if (!m_bIsBroken ) { Vector vSurfDir = ptr->endpos - ptr->startpos; Die( info.GetAttacker(), vSurfDir ); } if (info.GetDamageType() & (DMG_BULLET | DMG_CLUB)) { // Figure out which panel has taken the damage and break it float flWidth,flHeight; PanePos(ptr->endpos,&flWidth,&flHeight); int nWidth = flWidth; int nHeight = flHeight; if ( ShatterPane(nWidth, nHeight,vecDir*500,ptr->endpos) ) { //============================================================================= // HPE_BEGIN: // [dwenger] Window break stat tracking //============================================================================= CBasePlayer* pAttacker = ToBasePlayer(info.GetAttacker()); if ( ( pAttacker ) && ( !bWasBroken ) ) { gamestats->Event_WindowShattered( pAttacker ); } //============================================================================= // HPE_END //============================================================================= // Do an impact hit CEffectData data; data.m_vNormal = ptr->plane.normal; data.m_vOrigin = ptr->endpos; CPASFilter filter( data.m_vOrigin ); // client cannot trace against triggers filter.SetIgnorePredictionCull( true ); te->DispatchEffect( filter, 0.0, data.m_vOrigin, "GlassImpact", data ); } if (m_nSurfaceType == SHATTERSURFACE_GLASS) { // Break nearby panes if damages was near pane edge float flWRem = flWidth - nWidth; float flHRem = flHeight - nHeight; if (flWRem > 0.8 && nWidth != m_nNumWide-1) { ShatterPane(nWidth+1, nHeight,vecDir*500,ptr->endpos); } else if (flWRem < 0.2 && nWidth != 0) { ShatterPane(nWidth-1, nHeight,vecDir*500,ptr->endpos); } if (flHRem > 0.8 && nHeight != m_nNumHigh-1) { ShatterPane(nWidth, nHeight+1,vecDir*500,ptr->endpos); } else if (flHRem < 0.2 && nHeight != 0) { ShatterPane(nWidth, nHeight-1,vecDir*500,ptr->endpos); } // Occasionally break the pane above me if (random->RandomInt(0,1)==0) { ShatterPane(nWidth, nHeight+1,vecDir*1000,ptr->endpos); // Occasionally break the pane above that if (random->RandomInt(0,1)==0) { ShatterPane(nWidth, nHeight+2,vecDir*1000,ptr->endpos); } } } } else if (info.GetDamageType() & (DMG_SONIC | DMG_BLAST)) { // ---------------------------------------- // If it's tile blow out nearby tiles // ---------------------------------------- if (m_nSurfaceType == SHATTERSURFACE_TILE) { // Figure out which panel has taken the damage and break it float flWidth,flHeight; if (info.GetAttacker()) { PanePos(info.GetAttacker()->GetAbsOrigin(),&flWidth,&flHeight); } else { PanePos(ptr->endpos,&flWidth,&flHeight); } int nWidth = flWidth; int nHeight = flHeight; // Blow out a roughly circular patch of tile with some randomness for (int width =nWidth-4;width<nWidth+4;width++) { for (int height =nHeight-4;height<nHeight+4;height++) { if ((abs(nWidth-width)+abs(nHeight-height))<random->RandomInt(2,5)) { ShatterPane(width, height,vecDir*500,ptr->endpos); } } } } // ---------------------------------------- // If it's glass blow out the whole window // ---------------------------------------- else { //============================================================================= // HPE_BEGIN: // [pfreese] Window break stat tracking //============================================================================= CBasePlayer* pAttacker = ToBasePlayer(info.GetAttacker()); if ( ( pAttacker ) && ( !bWasBroken ) ) { gamestats->Event_WindowShattered( pAttacker ); } //============================================================================= // HPE_END //============================================================================= float flDot = DotProduct(m_vNormal,vecDir); #ifdef CSTRIKE_DLL float damageMultiplier = info.GetDamage(); #else float damageMultiplier = 1.0f; #endif Vector vBlastDir; if (flDot > 0) { vBlastDir = damageMultiplier * 3000 * m_vNormal; } else { vBlastDir = damageMultiplier * -3000 * m_vNormal; } // Has the window already been destroyed? if (m_nNumBrokenPanes >= m_nNumWide*m_nNumHigh) { return; } // --------------------------------------------------------------- // If less than 10% of my panels have been broken, blow me // up in one large glass shatter // --------------------------------------------------------------- else if ( m_nNumBrokenPanes < 0.1*(m_nNumWide*m_nNumHigh)) { QAngle vAngles; VectorAngles(-1*m_vNormal,vAngles); CreateShards(m_vCorner, vAngles,vBlastDir, ptr->endpos, m_nNumWide*m_flPanelWidth, m_nNumHigh*m_flPanelHeight, WINDOW_LARGE_SHARD_SIZE); } // --------------------------------------------------------------- // Otherwise break in the longest vertical strips possible // (to cut down on the network bandwidth) // --------------------------------------------------------------- else { QAngle vAngles; VectorAngles(-1*m_vNormal,vAngles); Vector vWidthDir,vHeightDir; AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); for (int width=0;width<m_nNumWide;width++) { int height; int nHCount = 0; for ( height=0;height<m_nNumHigh;height++) { // Keep count of how many panes if (!IsBroken(width,height)) { nHCount++; } // Shatter the strip and start counting again else if (nHCount > 0) { Vector vBreakPos = m_vCorner + (width*vWidthDir*m_flPanelWidth) + ((height-nHCount)*vHeightDir*m_flPanelHeight); CreateShards(vBreakPos, vAngles, vBlastDir, ptr->endpos, m_flPanelWidth, nHCount*m_flPanelHeight, WINDOW_LARGE_SHARD_SIZE); nHCount = 0; } } if (nHCount) { Vector vBreakPos = m_vCorner + (width*vWidthDir*m_flPanelWidth) + ((height-nHCount)*vHeightDir*m_flPanelHeight); CreateShards(vBreakPos, vAngles, vBlastDir, ptr->endpos, m_flPanelWidth,nHCount*m_flPanelHeight, WINDOW_LARGE_SHARD_SIZE); } } } BreakAllPanes(); } } }