//------------------------------------------------------------------------------
// 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 );
				}
			}
		}
	}
}
예제 #2
0
/*
================
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) );
		}
	}
}
예제 #4
0
/*
================
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
}
예제 #7
0
// 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);
      }
   }
}
예제 #8
0
/*
================
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;
}
예제 #10
0
/*
================
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 );
}
예제 #11
0
// 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;
  }
}
예제 #12
0
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;
}
예제 #13
0
// 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;
   }
}
예제 #14
0
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();
		}
	}
}