Forum

Snippet

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Postby thorn3001 » Thu Jun 30, 2011 6:44 pm

Very good contribution, thank you.
Although still not quite understand QC
User avatar
thorn3001
 
Posts: 29
Joined: Tue Jun 28, 2011 6:09 am
Location: Bogotá, Col

Postby toneddu2000 » Fri Jul 01, 2011 6:57 am

@behind_you: yes, it could be a smart way to have a "story map", just like Penumbra series!Thanks!
toneddu2000
 
Posts: 1352
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Postby behind_you » Sat Jul 02, 2011 6:30 am

You're welcome, thorn3001. Just keep at it. It's tricky at first but you'll get it (I am a noob myself, infact)

toneddu2000 you might want to check this out.

This is a very useful code I have for you today. Whenever you want to print a very long string that would surpass the screen resolution, you would be forced to either print the text one line after the other or spam "\n" newlines. This code takes your long string and arranges it into paragraph form for easier printing! Basically all you would have to do is input your string directly, without the use of any "\n". The code inserts a newline every time the amount of characters in the text surpasses the 'LINELIMIT' adjustable global float. This code doesn't newline in the middle of a word. It instead only newlines when the last character in the string is a blank space and if no blank space is found, the text searches backwards until it finds a blank space and newlines there. This makes sure that your paragraphs don't look stupid with words being divided to the next line. As an added effect, you can decide whether to center the paragraph or adjust it to the left!

This code took me an hour and a bit to finish. It will work with any engine that has the improved substring extension. Here is the function you will need:

Code: Select all
float LINELIMIT = 60;//This is how many characters will fit per line

void(float alignleft, string towrite) paragraphprint =
{
   local string firsthalf, newhalf, secondhalf, extras, spacecheck, blanks, justincase;
   local float charcount, secondhalfcount, looptimes, extraadd, blankcount, spaceremoved;
   
   charcount = strlen(towrite);
   
   if (charcount > LINELIMIT)
      {
      secondhalfcount = charcount;
      while(secondhalfcount > LINELIMIT)//master loop
         {
         looptimes = looptimes + 1;
         newhalf = substring(towrite, LINELIMIT * (looptimes - 1) - extraadd, LINELIMIT);
         spaceremoved = 0;
         spacecheck = substring(newhalf, spaceremoved, 1);
         while(spacecheck == " ")
            {
            if (looptimes == 1)
               break;
            spaceremoved = spaceremoved + 1;
            newhalf = substring(newhalf, spaceremoved, charcount);
            spacecheck = substring(newhalf, spaceremoved, 1);
            }
         extras = substring(newhalf, strlen(newhalf) - 1, 1);
         justincase = newhalf;
         while(extras != " ")
            {
            extraadd = extraadd + 1;
            newhalf = substring(newhalf, 0, strlen(newhalf) - 1);
            if (strlen(newhalf) <= floor(LINELIMIT / 8))
               {
               extraadd = 0;
               newhalf = justincase;
               break;
               }
            extras = substring(newhalf, strlen(newhalf) - 1, 1);
            }
         if (alignleft)
            {
            blanks = "";
            blankcount = LINELIMIT - strlen(newhalf);
            while(blankcount > 0)
               {
               blanks = strcat(blanks, " ");
               blankcount = blankcount - 1;
               }
            newhalf = strcat(newhalf, blanks);
            }
         firsthalf = strcat(firsthalf, newhalf, "\n\n");
         secondhalf = substring(towrite, (LINELIMIT * looptimes) - extraadd, charcount);
         secondhalfcount = strlen(secondhalf);
         }

      if (alignleft)
         {
         blanks = "";
         blankcount = LINELIMIT - secondhalfcount;
         while(blankcount > 0)
            {
            blanks = strcat(blanks, " ");
            blankcount = blankcount - 1;
            }
         secondhalf = strcat(secondhalf, blanks);
         }

      towrite = strcat(firsthalf, secondhalf);
      }

   centerprint(self, towrite);
};


This code is way to extensive to comment every line, so I will give a basic description of what's being done for you:

1- It first checks to see if the string you want to print is longer than LINELIMIT. If not, it just centerprints it normally. If it is, we continue.

2- We first have our master 'while' loop. This loop will continue as long as we have a line of text that is longer than the LINELIMIT global float.

3- 'looptimes' is a local float that counts how many times we loop, as this number is needed.

4- 'newhalf' is being set to read the text from the LINELIMIT multiplied by looptimes - 1(first time always equals 0) and reads up to the LINELIMIT amount of characters. When it does this the first time, it reads from the beginning of the text up to LINELIMIT amount of characters. You'll notice that it also subtracts the start position of the string by a float called 'extraadd'. I'll explain myself later.

5- Now the string 'spacecheck' checks to see if the beginning of any lines after the first line starts with a blank space. If a space is found, another while loop is initiated designed to remove all spaces found in the beginning of the line of text. Not doing this could make the text look odd, especially if aligned to the left.

6- 'extras' is a very useful string here. This while loop prevents the code from newlining in the middle of a word. If no blank space is found, the value of extraadd increases while the newhalf string decreases by 1. The characters removed from the newhalf string here will be added to the next newhalf string (hence subtracting the extraadd from the beginning newhalf substring). Just in case there is no blank spaces found in the line of text after a long time, the newhalf string reverts to its original form (thanks to 'justincase') before this while loop, extraadd is reset and this small while loop is broken.

7- If you set the 'alignleft' parameter to TRUE, this will cause the text to be adjusted to the left here (if not, the paragraph will be centered instead). This is done by counting the number of characters (including spaces) in the line and subtracting it from the LINELIMIT. Blank spaces are then added to the end of the string until the string's amount of character exactly equals the LINELIMIT. This causes the engine to center all lines of the text the same way and when you look at it, the text is aligned to the left.

8- Now the string 'firsthalf' combines it's original value (firsthalf has no value when this is executed the first time) and the newhalf value together every time the above steps are completed. The secondhalf string becomes equal to all the remaining characters. It then recounts how many characters are left. If the amount of characters left is less than LINELIMIT, we end the master loop. Otherwise, REPEAT!!

9- When the master loop is finished, if you set the 'alignleft' parameter to TRUE, the remaining characters are adjusted similarily to how newhalf was adjusted in step 7.

10- After all the work, we combine our results into our 'towrite' string and centerprint it!

If you want, adjust the global float LINELIMIT to hold as many characters you want in every line. This float is changeable in the middle of a game as well so feel free to do so!

To use this function, make your QC execute this function:

paragraphprint (ALIGN, WHATTOTYPE);

Set ALIGN to TRUE if you want to align your paragraph to the left. Set it as FALSE to center your paragraph.
Set WHATTOTYPE to the text you want to paragraph. You should make it longer than the LINELIMIT float to see the code in action.

A really cool effect would be to justify the text. But this requires engine code to adjust character spacings in every line, blah blah blah...

Hope you like it! More snippets coming soon! Others might contribute, but I'm not certain. I will contribute though, so look out!
User avatar
behind_you
 
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Postby toneddu2000 » Sun Jul 03, 2011 8:11 pm

And here, behind_you created a word editor inside quakec! :)
Awesome! Thanks a lot, this comes really handy when you want to write very long paragraphs (end of a chapter, level istructions and so on)
You're becoming more proficient at quakec every day!
Well done!
toneddu2000
 
Posts: 1352
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Postby behind_you » Mon Jul 04, 2011 7:53 am

Thanks a lot!

Small contribution today. This float function returns either true or false depending on if the supplied float is an interger or not. (AKA if it has no decimal point)

Code: Select all
float(float num) intergercheck =
{

   num = floor(num) - num;//Subtract a floored version of the number by the number

   if (num)//if a number still exists (always will be less than 1)
      return FALSE;//return as false

   return TRUE;//otherwise, return true

};
User avatar
behind_you
 
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Postby OneManClan » Wed Jul 06, 2011 12:52 am

Hey behind_you,

These are Brilliant, thanks! Out of curiosity, I tried to combine paragraphprint AND initcharprint (!!!), Unfortunately is wasn't as simple as:

Code: Select all
//At the bottom of paragraphprint:

//centerprint(self, towrite);
   initcharprint(towrite);


Tried it, but nothing printed ... how complex it would be to combine these two functions? We could get a PAGE of scrolling text, ala Doom!!

[EDIT] Also, how can you make it so that the bigger the paragraph, the longer the text stays on the screen? I just tried to find 'the place where it is decided how long centerprint keeps the text on screen', but was unable! :?
OneManClan
 
Posts: 243
Joined: Sat Feb 28, 2009 2:38 pm

Postby behind_you » Wed Jul 06, 2011 7:05 am

Thanks a lot!

I tried combining the two of them as well but it yielded no results. I have no idea why this is the case. I think it's the newlines that are the source of the problem. I will look into that since it will be cool to have a letter by letter paragraph being printed!

About your other request, I whipped up 2 methods here (untested!). Replace the last line in paragraphprint, which is the centerprint, with this:

Code: Select all

local float timecount;

charcount = strlen(towrite);//have to figure out new length of paragraph, you can multiply charcount for an even more increased centerprint lifetime
while(timecount < charcount)
{
centerprint(self, towrite);
timecount = timecount + 1;
}

This will make a longer centerprint depending on text length. Tweak the charcount value to adjust length time.

The second method will work with any engine that has a cvar similar to DP's scr_centertime, which controls the length of centerprint life. Add this to end of function:

Code: Select all
local string lengthstring;

charcount = strlen(towrite);
lengthstring = ftos(charcount);

cvar_set("scr_centertime", lengthstring);

centerprint(self, towrite);


There you go!
User avatar
behind_you
 
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Postby behind_you » Sat Jul 09, 2011 8:15 am

Alright. I figured out why paragraphprint and charprint wouldn't work together. It turns out that I needed to strzone the string that I wanted to print. This basically means saving the string so that it can be recalled later. Only engines with strzone and the improved substring will work with this addition. I also added an entity slot so that you can decide which entity sees the printed text (usually set to 'self').

One problem: The constant centering of text with charprint(that I 'fixed' earlier) will return when you use paragraphprint + charprint. I have absoluely no clue why this happens. I'll try my best to fix it if I am able to. In the meantime:

Code: Select all
float textmode;
void() charprint =
{
   local float howmany, blankcount;
   local string text, blanks;

   howmany = strlen(toprint);//count how many letters to print
   if (howmany >= textpos)//if your printing position is smaller than or equal to the amount of letters in your text
      {
      textpos = textpos + 1;//add one to your textposition
      text = substring (toprint, 0, textpos);//this substrings your text by the value of textpos. So if textpos equaled 2 and the text to print was "PRINTING", you would print "PR". If it were 3, you would print "PRI" and so on. Since textpos goes up every time by 1, you would get a letter by letter printing effect
      if (!textmode)
         {
         while(blankcount < (howmany - textpos))//while loop: whenever the blankcount is smaller than the difference between the character count and the typing text position
            {
            blanks = strcat(blanks, " ");//add a blank to the blanks string
            blankcount = blankcount + 1;//add to the blankcount(prevents runaway loop and tempstring errors)
            }
         text = strcat(text, blanks);//combine the text and the blanks. The point of this is to get rid of the constant centering the engine does with centerprints, which IMO looks better to me. If you like it, then remove this strcat line and the while loop.
         }
      //Optional: Add a sound code here. This sound will be played every time an extra character is printed (A typewriter or keystroke sound is best)
      }
   else//otherwise
      {
      text = toprint;//print the whole text
      centerprint(self, text);//print the current text
      strunzone(toprint);//Remove the string from the string zone, or else...
      return;//End the loop which would cause the text to disappear in a few seconds
      }

   centerprint(self, text);//print the current text
   self.nextthink = time + 0.02;//loop in 0.02 seconds. Increase this value for a slowed print.
};

void(entity who, string whattowrite, float paragraphmode) initcharprint =
{
   toprint = strzone(whattowrite);//save what you want to write because it won't work otherwise
   textpos = 0;
   textmode = paragraphmode;
   //Resets all the globals once for use again
   who.think = charprint;
   who.nextthink = time + 0.1;//start printing!
};

void(entity who, float alignleft, string towrite, float printstyle) paragraphprint =
{
   local string firsthalf, newhalf, secondhalf, extras, spacecheck, blanks;
   local float charcount, secondhalfcount, looptimes, extraadd, blankcount, spaceremoved;
   
   charcount = strlen(towrite);
   
   if (charcount > LINELIMIT)
      {
      secondhalfcount = charcount;
      while(secondhalfcount > LINELIMIT)
         {
         looptimes = looptimes + 1;
         newhalf = substring(towrite, LINELIMIT * (looptimes - 1) - extraadd, LINELIMIT);
         spaceremoved = 0;
         spacecheck = substring(newhalf, spaceremoved, 1);
         while(spacecheck == " ")
            {
            spaceremoved = spaceremoved + 1;
            newhalf = substring(newhalf, spaceremoved, charcount);
            spacecheck = substring(newhalf, spaceremoved, 1);
            }
         extras = substring(newhalf, strlen(newhalf) - 1, 1);
         while(extras != " ")
            {
            extraadd = extraadd + 1;
            newhalf = substring(newhalf, 0, strlen(newhalf) - 1);
            if (strlen(newhalf) <= (LINELIMIT / 4))
               break;
            extras = substring(newhalf, strlen(newhalf) - 1, 1);
            }
         if (alignleft)
            {
            blanks = "";
            blankcount = LINELIMIT - strlen(newhalf);
            while(blankcount > 0)
               {
               blanks = strcat(blanks, " ");
               blankcount = blankcount - 1;
               }
            if (alignleft > 1)
               newhalf = strcat(blanks, newhalf);
            else
               newhalf = strcat(newhalf, blanks);
            }
         firsthalf = strcat(firsthalf, newhalf, "\n\n");
         secondhalf = substring(towrite, (LINELIMIT * looptimes) - extraadd, charcount);
         secondhalfcount = strlen(secondhalf);
         }
      secondhalfcount = strlen(secondhalf);
      if (alignleft)
         {
         blanks = "";
         if (alignleft > 1)
            secondhalfcount = secondhalfcount + 2;//Aligning to the right has adjustment problem in final line of text. Hacky fix ;D
         blankcount = LINELIMIT - secondhalfcount;
         while(blankcount > 0)
            {
            blanks = strcat(blanks, " ");
            blankcount = blankcount - 1;
            }
         if (alignleft > 1)
            secondhalf = strcat(blanks, secondhalf);
         else
            secondhalf = strcat(secondhalf, blanks);
         }
      towrite = strcat(firsthalf, secondhalf);
      }
   if (!printstyle)
      centerprint(who, towrite);
   else
      initcharprint(who, towrite, TRUE);//Print text letter by letter. Since this is in paragraph mode, we must put in TRUE or else it wouldn't print properly at all. Print effect is hard to read while printing. Needs fixing.
};


To use this, make your QC execute this function:

paragraphprint (ENTITY, ALIGNMENT, THETEXT, PRINTSTYLE);

ENTITY: The entity that will see the text being printed. Usually self.
ALIGNMENT: 0 = centered paragraph, 1 = aligned to left, 2 = aligned to right.
THETEXT: The text to print.
PRINTSTYLE: Set to 1 for letter by letter print effect(charprint()), or 0 for whole paragraph to simply appear.

To print one line of text letter by letter, I recommend you not use paragraphprint (until I fix it/if I can fix it :P) but use this:

initcharprint (ENTITY, THETEXT, FALSE);

Same deal with ENTITY and THETEXT as above. Keep the FALSE as is for an easier to read text while printing. If anyone has any questions, feel free to ask.
User avatar
behind_you
 
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Postby behind_you » Sat Jul 09, 2011 8:16 am

This is a simple CSQC function that allows you to draw an equiladeral triangle of any size you want.

Code: Select all
void drawtriangle (vector posi, float trisize, vector tricolor, float trialpha, float triflags, float upordown)
{
   vector point1, point2, point3;
   float calc;
   
   point1 = posi;
   point2 = posi;
   point2_x = point2_x + trisize;
   point3 = posi;
   point3_x = point3_x + (trisize / 2);
   calc = (trisize / 2) * (trisize / 2);
   calc = (trisize * trisize) - calc;
   calc = sqrt(calc);
   if (upordown)
      calc = calc * -1;

   point3_y = point3_y - calc;

   drawline(1, point1, point2, tricolor, trialpha, triflags);
   drawline(1, point2, point3, tricolor, trialpha, triflags);
   drawline(1, point3, point1, tricolor, trialpha, triflags);
}


To use this:
drawtriangle (POSITION, SIZE, COLOR, ALPHA, FLAGS, UPORDOWN);

POSITION: Place a vector here, this is where the triangle will be drawn.
SIZE: This float determines the size of the triangle.
COLOR: This vector determines the color of the triangle (between 0 - 1 Example: '0.5 0 0.1').
ALPHA: This float determines the transparency of the triangle.
FLAGS: This boolean float determines the flag set on the triangle. If set true, the transparency of the triangle will be affected by the color level (lower value color vector = more transparent triangle).
UPORDOWN: Set to true to have a triangle pointing downwards. Otherwise, set to false to have an upward triangle.

Enjoy!
User avatar
behind_you
 
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Postby Team Xlink » Sun Aug 07, 2011 1:18 am

toneddu2000 wrote:Hi Nahuel, can you post some link to the documentation of FRIK_FILE?
Is it the same of this?


http://www.quake-1.com/docs/quakesrc.org/144.html
http://www.quake-1.com/docs/quakesrc.org/142.html
http://www.quake-1.com/docs/quakesrc.org/141.html
Team Xlink
 
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Previous

Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest