Best Extender functions - Pseudo Module

Started by Trent R, Wed 04/03/2009 08:23:09

Previous topic - Next topic

Trent R

I'm starting to create a pseudo-module script filled with Extender functions. So far they're all math ones, plus one character. Are there any all-purpose extender functions that you have in your game? Please share them and suggestions for others.

~Trent


Initial post: character.LossAllInv, Maths.Abs,Min,Max
Update 1: character.LoseAllInventory, LoseInventoryMult, AddInventoryMult, SetWalkingSound, RemoveAllWalkingSounds

character.Extenders
Code: ags
ViewFrame *frame;


void LoseAllInventory(this Character*){ //Character loses every single inventory item.
  int i = 1;
  while (i <= (Game.InventoryItemCount)){
    this.InventoryQuantity[i]=0; //Be warned: This doesn't pass anything to on_event
    i++;
  } 
  UpdateInventory();
}

void LoseInventoryMult(this Character*, InventoryItem *item, int count){ //Character loses specified number of inventory item.
  int i;
  while (i<count){
    this.LoseInventory(item);
    i++;
  } 
}

void AddInventoryMult(this Character*, InventoryItem *item, int count){ //Character gains specified number of inventory item.
  int i;
  while (i<count){
    this.AddInventory(item);
    i++;
  } 
}


void SetWalkingSound(this Character*, int Sound, int Frame, int Frame2){
  int i=0, max=0;
  if(Game.GetLoopCountForView(this.NormalView)<8)  max = Game.GetLoopCountForView(this.NormalView);
  else   max = 8;
  while(i<max){ 
    frame = Game.GetViewFrame(this.NormalView, i, Frame);
    frame.Sound=Sound;
    if(Frame2!=-1){  
      frame = Game.GetViewFrame(this.NormalView, i, Frame2);
      frame.Sound=Sound;  
    }
    i++;
  }
}

void RemoveAllWalkingSounds(this Character*){
  int i=0, j=0, max;
  if(Game.GetLoopCountForView(this.NormalView)<8)  max = Game.GetLoopCountForView(this.NormalView);
  else  max = 8;
  while(i<max){ 
    while(j<Game.GetFrameCountForLoop(this.NormalView, i)){
      frame = Game.GetViewFrame(this.NormalView, i, j);
      frame.Sound=0;
      j++;
    }
    j=0;
    i++;
  } 
}
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

Dualnames

Dare I suggest you add a Abs float function as well. And an Abs min, max. Anyways, my thoughts on that are really really positive.
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

Trent R

Actually, I almost put AbsInt and AbsFloat as different functions. Would that really be useful? (I honestly have only used floats once so far in my project--trig functions)
Same with MinFloat, MaxFloat?

~Trent
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

monkey0506

#3
I realize it's a pseudo module but it's also written in pseudo code. You cannot possibly make an extender method for the Maths structure and actually use it. Maths is a managed struct which solely provides static methods.

The fact that it's managed means you cannot create an instance of it.

The fact that you can't create/point-to an instance means that you can never call your extender method.

Beyond that, I would say that based on the fact the entire structure only accepts float parameters that making the functions take floats would be more streamlined to the built-in methods.

Besides int->float->int is okay. float->int->float is bad.

And if you're setting the inventory quantity to 0, is it really necessary to check if the character had the item to begin with?

If you insist on checking, I'd suggest you use this.InventoryQuantity > 0 instead of the function. Depending how many inventory items you actually have it could stand to be much faster that way with the reduced overhead.

As far as the static extenders, I've brought it up before somewhere. CJ said he'd consider it for a later version but it's not very high priority.

GarageGothic

I did the exact same thing, and yes, I created separate functions (AbsInt, AbsFloat, MaxInt, MaxFloat and so on) mainly for speed. I used them in line drawing algorithms, so I suspect using Int when applicable strains the CPU. Another thing I did was making the parameters optional by putting out-of-range default values that the function checks for.

But it is indeed annoying that you can't extend managed structs, it would make a lot of my utility functions seem much more intuitive and part of AGS.

Trent R

QuoteYou cannot possibly make an extender method for the Maths structure and actually use it. Maths is a managed struct which solely provides static methods.
The fact that it's managed means you cannot create an instance of it.
Just realized minutes ago about the managed type... I guess a Math or MathHelper struct would be best... and probably a different module too.

QuoteBesides int->float->int is okay. float->int->float is bad.
I'm trying to see where I've done that... are you speaking of if I could extend the Maths struct?

QuoteAnd if you're setting the inventory quantity to 0, is it really necessary to check if the character had the item to begin with?
If you insist on checking, I'd suggest you use this.InventoryQuantity > 0 instead of the function. Depending how many inventory items you actually have it could stand to be much faster that way with the reduced overhead.
As for that, it was cause I was thinking in my head of a LoseInventoryMult function, which I ended up writing differently.


Thanks for the input so far, I highly admire each of you guys.

~Trent
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

monkey0506

Quote from: Trent R on Wed 04/03/2009 09:35:37
QuoteBesides int->float->int is okay. float->int->float is bad.
I'm trying to see where I've done that... are you speaking of if I could extend the Maths struct?

No, you haven't. I was simply stating for the purposes of the end-user.

With the integer-based functions, the only way to pass floating point data through would be to convert it to integer, get the result, and convert back. Which results in a loss of data. The conversion from integer data to floating point and back is much less likely to cause problems (in the event you had only floats as parameters).

Joseph DiPerla

Joseph DiPerla--- http://www.adventurestockpile.com
Play my Star Wars MMORPG: http://sw-bfs.com
See my Fiverr page for translation and other services: https://www.fiverr.com/josephdiperla
Google Plus Adventure Community: https://plus.google.com/communities/116504865864458899575

Joe

I like this and I'd like to share this with you, I'm not thinking of doing any module by now... so you can copy, modify or discard it.

Code: ags


//-------------------HEADER--------------------------

import void SetWalkingSound(this Character*, int Sound, int Frame, int Frame2=-1);

import void RemoveAllWalkingSounds(this Character*);

//-------------------SCRIPT---------------------------

ViewFrame *frame;

void SetWalkingSound(this Character*, int Sound, int Frame, int Frame2){
  int i=0, max=0;
  
  if(Game.GetLoopCountForView(this.NormalView)<8)
    max = Game.GetLoopCountForView(this.NormalView);
  else
    max = 8;
    
  while(i<max){ 
  
    frame = Game.GetViewFrame(this.NormalView, i, Frame);
    frame.Sound=Sound;

    if(Frame2!=-1){  
      
      frame = Game.GetViewFrame(this.NormalView, i, Frame2);
      frame.Sound=Sound;  
  
    }
      
    i++;
  }
  
}

void RemoveAllWalkingSounds(this Character*){
  int i=0, j=0, max;
  
  if(Game.GetLoopCountForView(this.NormalView)<8)
    max = Game.GetLoopCountForView(this.NormalView);
  else
    max = 8;
    
  while(i<max){ 
    while(j<Game.GetFrameCountForLoop(this.NormalView, i)){
      
      frame = Game.GetViewFrame(this.NormalView, i, j);
      frame.Sound=0;
   
      j++;
    }
    j=0;
    i++;
  }
  
}

Copinstar © Oficial Site

Trent R

#9
To monkey: I figured out why I didn't realize sooner that this Maths* wouldn't work The extender function actually compiles and imports fine. But if you try to use it, you get one of three errors. CJ: Could that possibly been an error/warning that shows? But then again, it's very low priority too.

Anyways, I updated the original post. Changed LoseAllInventory due to what monkey siad. Added LoseInventoryMult and AddInventoryMult. And also Joe's SetWalkingSound and RemoveAllWalkingSounds (I haven't used sounds much, but that seems like it'd be useful for switching floor materials--Like Trilby or ATOTK)


~Trent
PS - I'm so psyched that I figured out (by accident) that /// comments work! I knew they did that in C#, but it always created the <summary> and <param> tags for you, so I assumed AGS couldn't do that yet. Couldn't be more excited!
To give back to the AGS community, I can get you free, full versions of commercial software. Recently, Paint Shop Pro X, and eXPert PDF Pro 6. Please PM me for details.


Current Project: The Wanderer
On Hold: Hero of the Rune

monkey0506

The problem with trying to extend the Maths structure is that your extender method in and of itself is 100% valid. It shouldn't throw any errors or exceptions. So the fact that it compiles is correct.

The problem arises in the fact that the structure doesn't provide any access to these methods. As I said, I suggested once before that static extenders become possible, but it was rated as a low-priority request.

Definitely being able to make your custom functions better in alignment with the built-in functions, providing seamless integration for the end-user, is highly desirable. However if you think about it, it's really only a difference of how the function gets called:

Code: ags
// with extender method
int abs = Maths.Abs(-105);


Could just as easily be:

Code: ags
// without extenders
int abs = Maths_Abs(-105);


It's reasonably not something that, IMO at least, should be considered as high priority, especially given some of the other items which are still pending implementation.

The /// comments for the calltip help text is very useful. I have myself used it in my modules since CJ introduced that feature to clarify to the end-user what the functions are and where they're coming from. Especially useful as we enter the realm of extender methods. := Just my two cents, but I've been doing it something like this:

///Module name: Description of function and parameters.

Prefixing the module name makes sure the user knows where to seek resolution if they have any questions/comments/death-threats. Certainly I wouldn't want someone coming around spamming CJ via PM over some code that I wrote not working! 8)

Lt. Smash

#11
here are some string extenders. Maybe someone can use them.

Code: ags

String InsertCharAt(this String*, int index, char newChar) {
	if (index < 1 && this.Length < 1)
		return this.AppendChar(newChar);
	String a = "", b = "";
	if (index == 0) a = this.Substring(index, this.Length);
	else a = this.Substring(index, this.Length-1);
	b = this.Truncate(index);
	b = b.AppendChar(newChar);
	b = b.Append(a);
	return b;
}

String DeleteCharsAt(this String*, int index, int length){
	if (index <= 0 && this.Length <= 0)
		return this;
	else if (index+length > this.Length)
		return this;
	String a = "", b = "";
	a = this.Substring(index+length, this.Length-1);
	b = this.Truncate(index);
	b = b.Append(a);
	return b;
}

int IndexOfStart(this String*, String sub, int start) {
    if(start >= this.Length - sub.Length) return -1;
    if(start <= 0) return this.Contains(sub);
    String e = this.Substring(start, this.Length - start);
    int i = e.Contains(sub);
    if(i >= 0) i += start;
    return i;
}

int Split(this String*, String separator, String array[]) {
    int n = this.Length;
    int start, stop, i;
    while(start >= 0 && start < n) {
      stop = this.IndexOfStart(separator, start);
      if(stop < 0 || stop > n) stop = n;
      if(stop>start) {
         array[i] = this.Substring(start, stop-start);
         i++;
      }
      start = stop+separator.Length;
    }
    return i;
}

RickJ

Perhaps String extensions should be in their own module?

monkey0506

#13
An InsertStringAt function could be useful, but wouldn't it be simpler as:

Code: ags
String InsertStringAt(this String*, int index, String otherString) {
  if (String.IsNullOrEmpty(otherString)) return this;
  if (index <= 0) return otherString.Append(this);
  if (index >= this.Length) return this.Append(otherString);
  return String.Format("%s%s%s", this.Substring(0, index), otherString, this.Substring(index, this.Length));
}


Rick, on that note, I have already written all of these functions if anyone's interested:

List moved to appropriate thread

I'm not sure how many of those might already have been included in a release of my module, but I went off on a tangent about REGEX and I know that the most recent functions never got released.

Edit: 13 March 2009, I updated the list of functions to reflect what I've currently been working on. There might be a few more planned, and I'm actually planning another release of my StrAdditions module shortly.

SMF spam blocked by CleanTalk