Minor requests for the next release

Minor requests for the next release

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Minor requests for the next release

Post by colorblind »

I have some minor requests for the next release:
  • Have the .info and .clock automatically displayed at startup.
  • When a player dies, he automatically becomes a spectator.
    • Fix the CTRL-A CTRL-D issue for not finished buildings (they don't die after a CTRL-A CTRL-D).
Can't think of any more atm. Imho this will fix some common annoyances. It probably shouldn't be too hard to implement these; hence I dare to make these requests.

EDIT: I've posted some codechanges to these requests below.
Last edited by colorblind on 11 Jul 2005, 23:53, edited 1 time in total.
User avatar
Min3mat
Posts: 3455
Joined: 17 Nov 2004, 20:19

Post by Min3mat »

u can't self destruct a unfinished building! <.< and why would you want to :s if you want to quit... shift esc? and buildings kill themselves pretty quickly anyway!!! >.>
somewhere in the debug screen ('b') have player units as the total units isn't much use!
Fix the unit stuck in factory bug (i think you said somewhere that you were going to do something with the grid ?)
Port a more recent version of AA? it looks like a good game but the current version is buggy and certain things (which make AA tactical) don't work (paralysers etc.) I know this is mostly a thread for requests from the SYs but i don't see why i can't post requests other people could implement :p
Auto spectator would suck unless that person was mute. when you are playing online vs randoms they can give advice etc to their teammate >.< I like the way the host has the power to enable cheats (the host should have more power imo :)) so you can make sure you only do it to people you trust
A r: command, much like the a: command but instead allows only spectators to see. this would be AMAZING for reviews, you could actively review a game whilst watching, then simply upload the replay to FU!!! THAT WOULD BE AWESOME!!! :)
^
Erm if that is implemented i'd give you errrr somthing valuable? :) please someone do it!!! :twisted:
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Min3mat wrote:u can't self destruct a unfinished building! <.< and why would you want to :s if you want to quit... shift esc? and buildings kill themselves pretty quickly anyway!!! >.>
It's pretty lame when a player who is on the losing side simply quits the game before selfdestructing. And half-finished buildings kill themselves pretty damn slowly, especially when it's something expensive like a bertha or fusion.
Min3mat wrote:when you are playing online vs randoms they can give advice etc to their teammate
Good point. I had some code already figured out ... sigh ... have to redo that. How does "when an ally team dies, all teammembers become spectators" sound?
Anyway, I did some digging and came up with the following solutions.

(1) The auto-info and -clock.
In game.cpp change lines 147-148 from

Code: Select all

	showClock=false;
	showPlayerInfo=false;
to

Code: Select all

	showClock=true;
	showPlayerInfo=true;
(3)Self destruct of not-finished building
In unit.cpp change lines 322-344 from

Code: Select all

	if(beingBuilt){
		if(lastNanoAdd<gs->frameNum-200){
			health-=maxHealth/(buildTime*0.03);
			buildProgress-=1/(buildTime*0.03);
			AddMetal(metalCost/(buildTime*0.03));
			if(health<0)
				KillUnit(false,true);
		}
		return;
	}
	//below is stuff that shouldnt be run while being built
	if(selfDCountdown){
		selfDCountdown--;
		if(selfDCountdown<=1){
			KillUnit(true,false);
			selfDCountdown=0;
			return;
		}
		ENTER_MIXED;
		if(selfDCountdown&1 && team==gu->myTeam)
			info->AddLine("%s: Self destruct in %i s",unitDef->humanName.c_str(),selfDCountdown/2);
		ENTER_SYNCED;
	}
to

Code: Select all

	if(selfDCountdown){
		selfDCountdown--;
		if(selfDCountdown<=1){
			KillUnit(true,false);
			selfDCountdown=0;
			return;
		}
		ENTER_MIXED;
		if(selfDCountdown&1 && team==gu->myTeam)
			info->AddLine("%s: Self destruct in %i s",unitDef->humanName.c_str(),selfDCountdown/2);
		ENTER_SYNCED;
	}
	if(beingBuilt){
		if(lastNanoAdd<gs->frameNum-200){
			health-=maxHealth/(buildTime*0.03);
			buildProgress-=1/(buildTime*0.03);
			AddMetal(metalCost/(buildTime*0.03));
			if(health<0)
				KillUnit(false,true);
		}
		return;
	}
	//below is stuff that shouldnt be run while being built
I really don't know why the self-destruct code originally was placed after the building code ... But perhaps some can tell me a good reason for doing so.
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Ok, SY code like

Code: Select all

gs->allies[gs->team2allyteam[gs->players[inbuf[inbufpos+2]]->team]][gu->myAllyTeam]
is really hard to read.
So I'm just going to post the spectator thing I had found earlier that will change a player into a spectator after death. If one of the SY can give me some reference as to where player, team, and allyteam information is stored I'd be happy to change the following lines of code to "when an allyteam dies, all of its members become spectators".
But for now only the simple solution:

(2) A dead player becomes a spectator.
In team.cpp, add the following line:

Code: Select all

#include "GameSetup.h"
Change lines 203-206 from

Code: Select all

	if(units.empty()){
		info->AddLine("Team%i(%s) is no more",teamNum,gs->players[leader]->playerName.c_str());
		isDead=true;
	}
to

Code: Select all

	if(units.empty()){
		info->AddLine("Team%i(%s) is no more",teamNum,gs->players[leader]->playerName.c_str());
		isDead=true;
		for(int a=0;a<gameSetup->numPlayers;++a){
			if(gs->players[a]->team==teamNum){
                gs->players[a]->spectator=true;
				if(a==gu->myPlayerNum)
					gu->spectating=true;
			}
		}
	}
Dunno if this works correctly in all cases, but it does the ones I've tested.
User avatar
Min3mat
Posts: 3455
Joined: 17 Nov 2004, 20:19

Post by Min3mat »

allyteam dies thing sounds good...this would be good for ffas etc :D
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Don't I really have anything better to do? Guess not. So here's another one.
Min3mat wrote:A r: command, much like the a: command but instead allows only spectators to see.
In game.cpp, change lines 2194-2204 from

Code: Select all

	if((s[0]=='a' || s[0]=='A') && s[1]==':'){
		if(gs->allies[gs->team2allyteam[gs->players[inbuf[inbufpos+2]]->team]][gu->myAllyTeam] || gu->spectating){
			s="<"+gs->players[player]->playerName+"> Allies: "+s.substr(2,255);
			info->AddLine(s);
			sound->PlaySound(chatSound);
		}
	} else {
		s="<"+gs->players[player]->playerName+"> "+s;
		info->AddLine(s);
		sound->PlaySound(chatSound);
	}
to

Code: Select all

	if((s[0]=='a' || s[0]=='A') && s[1]==':'){
		if(gs->allies[gs->team2allyteam[gs->players[inbuf[inbufpos+2]]->team]][gu->myAllyTeam] || gu->spectating){
			s="<"+gs->players[player]->playerName+"> Allies: "+s.substr(2,255);
			info->AddLine(s);
			sound->PlaySound(chatSound);
		}
	}
	if((s[0]=='s' || s[0]=='S') && s[1]==':'){
		if(gu->spectating || gu->myPlayerNum == player){
			s="<"+gs->players[player]->playerName+"> Spectators: "+s.substr(2,255);
			info->AddLine(s);
			sound->PlaySound(chatSound);
		}
	}else {
		s="<"+gs->players[player]->playerName+"> "+s;
		info->AddLine(s);
		sound->PlaySound(chatSound);
	}
That should work,but I don't mind if someone checked.
Min3mat wrote:Erm if that is implemented i'd give you errrr somthing valuable?
What did you have in mind? ;)
User avatar
Buggi
Posts: 875
Joined: 29 Apr 2005, 07:46

Post by Buggi »

Lemme try to help the readness...

Code: Select all

gs->allies[gs->team2allyteam[gs->players[inbuf[inbufpos+2]]->team]][gu->myAllyTeam]
"gs" is everything that is sync'ed for users. "Globally Sync'ed"

"allies" contains the alliances in the current game, as a 2 dimensional array, player-team pairs.

Thusly

Code: Select all

allies[gs->team2allyteam[gs->players[inbuf[inbufpos+2]]->team]]
Accesses the allies array in position [ team2[playerX] team]

And the second pair of brackets

Code: Select all

[gu->myAllyTeam]
Uses "gu" which is unsync'ed stuff getting "myAllyTeam" most likely loaded from the script.txt file generated.

-Buggi
shnorb
Posts: 147
Joined: 04 Jun 2005, 07:25

Post by shnorb »

is it possible to have to have spectating enabled whenever anyone dies, but simply have team chat disabled for them? also, what is the reason for being able to teamchat when spectating in a game...? i think this could and probably has been used to the advantage/disadvantage of players as you could do that with your friend or something like that... i think a cool thing to do (although this is a client gui thingo) would be that before joining a game spectators could be able to pick the team they go on... or pick 'none'

does anyone follow what ive said or am i just rambling? (please dont say im just rambling :-) )

EDIT: i think that the .clock and .info should be reversed, so that its always on, but you can turn them off by typing it in...
SJ
Posts: 618
Joined: 13 Aug 2004, 17:13

Post by SJ »

Ok I will include those stuff although somewhat tweaked.
User avatar
Min3mat
Posts: 3455
Joined: 17 Nov 2004, 20:19

Post by Min3mat »

including the r: command? that imo would be the bestest ever, no need fora lenghty text review, just a all in one replay file u can d/l
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

SJ wrote:Ok I will include those stuff although somewhat tweaked.
Great! And you will have to forgive me for my not-so-perfect programming skills; I've copy-pasted most of the stuff because my C++ isn't that good :P

Oh, and Buggi (or someone else interested), it would be really useful to have some documentation on the most important variables used in the code (hint hint).

And the rambling goes on: I have yet some requests to make, this time concerning the replays:
  • Have the replay file written out in a /demos or /replays directory
  • Change the replay filename to demo001.sdf (or something similiar)
    • If demoX.sdf exists, call the new replay demoX+1.sdf
  • Have statistics of the game written out in a file demo001.txt, which will include:
    • Spring version number
    • Mapname
    • Playernames + ally information
    • Who won
    • Other end-game statistics when they become availabe (amount of resources, no. of units killed, etc).
Perhaps the Spring versionnumber and the mapname should be included in the replay-filename. That way it can be instantly posted to FU or the likes.
shnorb
Posts: 147
Joined: 04 Jun 2005, 07:25

Post by shnorb »

having every replay saved would take up some serious hard drive space with the amount of online playing im doing... maybe you could set the limit of saved replays you want, after that it starts saving over the top of the oldest one... that would be good! :P
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Or perhaps a pop-up at the end of the game: "Do you want to save this replay?"
SJ
Posts: 618
Joined: 13 Aug 2004, 17:13

Post by SJ »

Demo files usually dont get bigger than a few megs so I dont think space will be a problem.

Write some code for it and I will include it.
User avatar
Min3mat
Posts: 3455
Joined: 17 Nov 2004, 20:19

Post by Min3mat »

Write some code for it and I will include it.
So i assume you willl include colourblinds coding into the new spring version? it would really make my 'job' easier. tia
Betalord
Former Engine Dev
Posts: 543
Joined: 29 Jun 2005, 09:31

Post by Betalord »

Another suggestion: bind a separate key for "ally talk", like t or s or a or something, it's really annoying to type "a: " in front of everyhint you say.
Another one would be to enable word wrap in memo box because it's hard to read messags if the words are truncated in the middle.
User avatar
Neuralize
Posts: 876
Joined: 17 Aug 2004, 23:15

Post by Neuralize »

A screenshots directory would be nice too, it's a wee bit annoying to have to wade through a bunch of files in the spring directory. :/

I didn't glance at the code above too thoroughly, but couldn't the self-destruction of particually build units be abused?

*Brings in a throng of adv. construction aircraft, starts building nuke silo, control d.*

When control-ding a nano skeleton, it should just dissipate completely and not cause any sort of explosion.
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Neuralize wrote:When control-ding a nano skeleton, it should just dissipate completely and not cause any sort of explosion.
It does, so your worries are unjustified.

As for the screenshots directory:
Open game.cpp, change lines ~689-711 from

Code: Select all

	if (s=="screenshot"){
		int x=gu->screenx;
		if(gu->screenx%4)
			gu->screenx+=4-gu->screenx%4;
		unsigned char* buf=new unsigned char[gu->screenx*gu->screeny*4];
		glReadPixels(0,0,gu->screenx,gu->screeny,GL_RGBA,GL_UNSIGNED_BYTE,buf);
		CBitmap b(buf,gu->screenx,gu->screeny);
		b.ReverseYAxis();
		string name;
		for(int a=0;a<9999;++a){
			char t[50];
			itoa(a,t,10);
			name=string("screen")+t+".jpg";
			CFileHandler ifs(name);
			if(!ifs.FileExists())
				break;
		}
		b.Save(name);
		delete[] buf;
		gu->screenx=x;
	}
to

Code: Select all

	if (s=="screenshot"){
		int x=gu->screenx;
		if(gu->screenx%4)
			gu->screenx+=4-gu->screenx%4;
		unsigned char* buf=new unsigned char[gu->screenx*gu->screeny*4];
		glReadPixels(0,0,gu->screenx,gu->screeny,GL_RGBA,GL_UNSIGNED_BYTE,buf);
		CBitmap b(buf,gu->screenx,gu->screeny);
		b.ReverseYAxis();
		string name;
		string path="screenshots/";
		for(int a=0;a<9999;++a){
			char t[50];
			itoa(a,t,10);
			name=string("screen")+t+".jpg";
			name=path+name;
			CFileHandler ifs(name);
			if(!ifs.FileExists())
				break;
		}
		b.Save(name);
		delete[] buf;
		gu->screenx=x;
	}
As you can see it's a minor modifaction; I've only added the lines 'string path="screenshots/";' and 'name=path+name;'.
Note that this doesn't check if the directory 'path' exists. If it doesn't, Spring will give an error and exits when you try to make a screenshot. It should of course be extended to encompass this, but I couldn't be bothered ...
User avatar
munch
Posts: 311
Joined: 26 May 2005, 20:00

Re: Minor requests for the next release

Post by munch »

colorblind wrote:I have some minor requests for the next release:....
Could I add:
- a "play CORE" random enemies script as well as the "play ARM" one
- change random enemies scripts to use 1000/1000 resources
- reduce server menu font size so that we can see more than the first few maps!

Thanks

Munch
colorblind
Spring Developer
Posts: 374
Joined: 14 Mar 2005, 12:32

Post by colorblind »

Remember how I wanted multiple and text-commented replays? (see my previous post if you can't remember.)
Well, I've fiddled around in the source code and came up with something that writes demofiles into a demo/ with incrementing filename and accompanying text file. The text file looks like this:

Code: Select all

*****************************
*                           *
*    TA Spring demo file    *
*                           *
*****************************


Version:	0.51b2
Mapname:	SmallDivide.smf


================================================
Side	| Team	| Ally team	| Player
------------------------------------------------
arm 	| 3 	| 3 		| colorblind
arm 	| 2 	| 2 		| LewsTherin
arm 	| 1 	| 1 		| nuudleh
arm 	| 0 	| 0 		| mcdumpsterxi
================================================


================================================
Time	| Event
------------------------------------------------
00:18	| Team 3 (colorblind) was annihilated
00:31	| Team 0 (mcdumpsterxi) was annihilated
00:36	| Team 1 (nuudleh) was annihilated
Hmm ... the tabs looked okay in my text editor/viewer. Anyhow, the codechanges are below. They're quite reasonable in size, so take your time.

NET.H
In net.h change line 134

Code: Select all

	void CreateDemoFile(char* name);
to

Code: Select all

	char demoBinFile[50];
	char demoTxtFile[50];
	void CreateDemoFile(void);
NET.CPP
In net.cpp change line 153

Code: Select all

		CreateDemoFile("test.sdf");
to

Code: Select all

		CreateDemoFile();
Change the function CreateDemoFile (which begins on line 546) from

Code: Select all

void CNet::CreateDemoFile(char* name)
{
	recordDemo=new ofstream(name, ios::out|ios::binary);
	if(gameSetup){
		char c=1;
		recordDemo->write(&c,1);
		recordDemo->write((char*)&gameSetup->gameSetupTextLength,sizeof(int));
		recordDemo->write(gameSetup->gameSetupText,gameSetup->gameSetupTextLength);
	} else {
		char c=0;
		recordDemo->write(&c,1);
	}
}
to

Code: Select all

void CNet::CreateDemoFile()
{
	for(int a=0;a<9999;++a){
		sprintf(demoBinFile,"demos/demo%03i.sdf",a);
		sprintf(demoTxtFile,"demos/demo%03i.txt",a);
		CFileHandler ifs(demoBinFile);
		if(!ifs.FileExists())
			break;
	}
	
	recordDemo=new ofstream(demoBinFile, ios::out|ios::binary);
	if(gameSetup){
		char c=1;
		recordDemo->write(&c,1);
		recordDemo->write((char*)&gameSetup->gameSetupTextLength,sizeof(int));
		recordDemo->write(gameSetup->gameSetupText,gameSetup->gameSetupTextLength);

		ofstream fout(demoTxtFile, ios::trunc);
		fout << "*****************************\n";
		fout << "*                           *\n";
		fout << "*    TA Spring demo file    *\n";
		fout << "*                           *\n";
		fout << "*****************************\n";
		fout << "\n";
		fout << "\n";
		fout << "Version:\t" << game->version		<< "\n";
		fout << "Mapname:\t" << pregame->mapName	<< "\n";
		fout << "\n";
		fout << "\n";
		fout << "================================================\n";
		fout << "Side\t| Team\t| Ally team\t| Player\n";
		fout << "------------------------------------------------\n";
		for(int a=0;a<gameSetup->numPlayers;++a){
			if(!gs->players[a]->spectator){ // we don't care for spectators
				int team = gs->players[a]->team;
				fout << gs->teams[team]->side	<< " \t| "		<< team << " \t| ";
				fout << gs->team2allyteam[team] << " \t\t| "	<< gs->players[a]->playerName << "\n";
			}
		}
		fout << "================================================\n";
		fout << "\n";
		fout << "\n";
		fout << "================================================\n";
		fout << "Time\t| Event\n";
		fout << "------------------------------------------------\n";
		fout << flush;
		fout.close();
	} else {
		char c=0;
		recordDemo->write(&c,1);
	}
}
Pregame.h will have to be included for the mapname info. Furthermore I've introduced a 'Spring version' variable, which is stored in the game instance. Perhaps a global constant is better, but I'll leave that to the SY. Here's how I've put it in the game object:

GAME.H
In game.h, after

Code: Select all

class CGame : public CGameController
{
public:
add the following:

Code: Select all

	std::string version;
	std::string fullversion;
GAME.CPP
In game.cpp add after

Code: Select all

CGame::CGame(bool server,std::string mapname)
{
the following:

Code: Select all

	version		= "0.51b2";
	fullversion = "TA Spring " + version;
Change line 248 from

Code: Select all

	info->AddLine("TA Spring 0.51b1");
to

Code: Select all

	info->AddLine(fullversion);
I couldn't get this to work in myGL.cpp on line 84 with font->glPrintAt() ... looks like glPrintAt() is very picky with its arguments.
Anyway, back to demo text file.

TEAM.CPP
In teamp.cpp, add after lines 203-212

Code: Select all

	if(units.empty()){
		info->AddLine("Team %i (%s) is no more",teamNum,gs->players[leader]->playerName.c_str());
		isDead=true;
		for(int a=0;a<MAX_PLAYERS;++a){
			...
		}
the following:

Code: Select all

		char time[10];
		sprintf(time,"%02i:%02i",gs->frameNum/60/30,(gs->frameNum/30)%60);
		ofstream fout(net->demoTxtFile, ios::app);
		fout << time << "\t| ";
		fout << "Team " << teamNum << " (" << gs->players[leader]->playerName << ") was annihilated\n";
		fout << flush;
		fout.close();
Net.h has to be included for getting net->demoTxtFile.

And of course I'd appreciate very much if this gets into the CVS :)
Post Reply

Return to “Engine”