--
[ Picked text/plain from multipart/alternative ]
Some good info. I learned a bit from it. I am by no means a professional
(anything), so take my comments with a grain of salt! This is all just my
own little opinion.
I can't speak for everyone, but to me it would seem like anyone who
understands basic programming concepts, functions, and methods (member
functions), should be able to realize they can call functions from anywhere
(inside Think functions). I'd recommend picking a target audience that
allows you to focus on explaining the purpose of the Think functions, how to
use them, and write as if you're talking to them. Organize the document in
such a way where it states its assumptions about the reader's knowledge,
where the reader can find information about those assumptions (if they don't
know those things), and then the document itself.
I know there is a DATADESC macro to define a Think function,
DEFINE_THINKFUNC. I'm not sure of what it gains you, however, and from what
I've been able to tell everything works fine without it. However, since it
exists, it may be good to understand the purpose of DATADESC so you can
describe what using that macro gains you. (This would teach me something
too!) Though, following what I mention in the paragraph above, I wouldn't
go into a lot of detail about the purpose of DATADESC itself. You could
write a separate document on that.
As for AI, at most I would suggest that these functions could be used for
AI, and then cover the AI in another document. Again, this keeps the
document focused on the Think functions and how to use them.
Elaborate a little on what "internal logic" is, as it's an important concept
in terms of what a Think function is for. Something like "Think functions
are used to implement your entity's internal logic, how your entity thinks.
In other words, an Entity can use a think function to determine how it
should react to external stimuli and its current situation. For example, an
entity that uses a weapon could use a Think function to check its current
ammunition stock. If its low, it would switch to another Think function
that implements how it should go about finding ammunition." This could tie
in well to the AI comment I made above.
You mention ClientThink at the beginning of the document, and then again at
the end. I'd put them together.
Are you sure the Think function is called automatically at Spawn? I always
thought you had to set the correct think function with SetThink, and call
SetNextThink from within Spawn() to get the a Think function to fire the
first time. I may be wrong here, and if so someone please correct me (I
don't have the code available to test it at the moment).
I'd mention that passing 0 (some code samples I've seen use NULL) to
SetNextThink will prevent a Think function from being fired again.
The code samples and explanations are perfect for how to use the Think
functions and how they're based on time. Also, the more advanced example
regarding the gun is a great way of showing how those functions can be
expanded into something more detailed, that's not necessarily "AI". In
other words, it's another use of the Think functions.
Finally, I would elaborate a little on what you mean by "Don't put anything
expensive in this function."
I think it's a very useful document, especially to someone just getting
started with the Source Engine. Great job!
- Josh
On Fri, Feb 22, 2008 at 11:56 AM, Tom Edwards <[EMAIL PROTECTED]>
wrote:
> [ Converted text/html to text/plain ]
>
> I'm in the process of writing some programming documentation for VDC (it's
> a
> fantastic way to learn). Before I make any changes, I'd like to hear some
> feedback. :-)
>
> Some concerns of mine:
>
> I don't explicitly mention that you can call the functions from anywhere
> within a class, not just a think function. How obvious is it that you can
> do
> that?
> I don't mention DATADESC. I don't understand it, can't make it work, and
> all
> of my experiments worked fine without it anyway. Is it important?
> I don't mention AI thinking. Should I?
> Is it actually any good?
>
> Here's the copy. I hope you can view HTML e-mails:
>
>
> ------------------------------------------------------------------------------
>
> Thinking
>
> An entity's Think() function is the "root" gateway used to run all
> internal
> logic. It is called once on spawn, with any subsequent calls decided by
> the
> programmer – happening either on a regular basis, or in response to
> external
> events.
>
> Use ClientThink()[1] to have an entity think every frame.
>
> SetNextThink()
>
> Defines when the entity next thinks.
> Accepts a floating point[2] value.
> If more than one call is made in a single execution, the new value
> overrides
> the old.
>
> void CMyEntity::Think()
> {
> Msg( "I think, therefore I am.\n" );
> SetNextThink( gpGlobals->curtime + 1.0f ); // Think again in 1.0seconds
> }
>
> This code causes the entity to print a message to the console once per
> second.
> Note the use of gpGlobals->curtime, which returns the time at execution,
> and f,
> which tells the C++ compiler that we are submitting a floating-point value
> and
> not an integer[3].
>
> SetThink()
>
> Changes the active think function
> Accepts a function pointer[4]: add '&' before the name and omit its
> closing parentheses.
> If more than one call is made in a single execution, the new value
> overrides
> the old.
>
> void CMyEntity::Think()
> {
> Msg( "I think, therefore I am.\n" );
> SetThink( &CMyEntity::Think2 ); // Think with this procedure next
> SetNextThink( gpGlobals->curtime + 1.0f );
> }
>
> void CMyEntity::Think2()
> {
> Msg( "Variety is the spice of life.\n" );
> SetThink( &CMyEntity::Think ); // Think with this procedure next
> SetNextThink( gpGlobals->curtime + 1.0f );
> }
>
> This code switches thinking between two functions. A real-world
> application is
> to change an entity between various life stages: consider a buildable gun
> turret[5]. One think function would run while it waits to be unpackaged,
> another while it is being built, another while it is active, and a fourth
> when
> it dies. Creating think functions for each discrete stage increases code
> stability and aids debugging.
>
> ClientThink()
>
> Thinking can also occur on the client, but its effects are limited.
> Additionally, only one think function is supported for each entity.
>
> void C_MyEntity::ClientThink()
> {
> DevMsg( "Don't put anything expensive in this function!\n" );
> SetNextClientThink( CLIENT_THINK_ALWAYS ); // Think every frame
> }
>
> Some examples of client-side thinking are:
>
> Visual effects / particles
> VGUI screen interaction
> Modifying player speed (calculated on the client as well as server to
> avoid
> lag)
> Striders' legs snapping ropes (disabled by default)
>
> SetNextClientThink()
>
> Used to re-fire ClientThink(). In addition to normal float values, it
> accepts:
>
> CLIENT_THINK_ALWAYS
> Think on the client once every frame. Use with caution!
> Replaces Simulate().
> CLIENT_THINK_NEVER
> Stop all client-side thinking without killing the entity.
>
> ===References:===
> 1.
> http://developer.valvesoftware.com/w/index.php?title=Generalities_On_Entities&action=submit#ClientThink.28.29
> 2. http://en.wikipedia.org/wiki/Floating_point
> 3. http://en.wikipedia.org/wiki/Integer_%28computer_science%29
> 4. http://en.wikipedia.org/wiki/Pointer_%28computing%29
> 5. http://forums.gamedesign.net/viewtopic.php?t=3702
>
> _______________________________________________
> To unsubscribe, edit your list preferences, or view the list archives,
> please visit:
> http://list.valvesoftware.com/mailman/listinfo/hlcoders
>
>
--
_______________________________________________
To unsubscribe, edit your list preferences, or view the list archives, please
visit:
http://list.valvesoftware.com/mailman/listinfo/hlcoders